为什么 '.'/3 会默默地将关联列表转换为字典?
Why does '.'/3 silently convert an associative list into a dict?
我在 SWI-Prolog 中进行了一些类型测试,偶然发现了字典和 Key=Value
术语列表之间的差异。或者更确切地说,我偶然发现了它们的相似之处。
根据SWI-Prolog manual dicts are "structures with named arguments" of the form Tag{Key1:Value1, Key2:Value2, ...}
. The manual mentions the predicates '.'/3
(section 4.2.1) and get_dict/3
(section 4.2.2) 从字典中提取值(其他谓词和功能符号故意省略)。谓词之间的区别在于,如果字典不包含所需的键,'.'/3
会引发异常,而 get_dict/3
会静默失败。然而,列表不是字典,即使有谓词将列表(键值关联的列表,例如 key:value
或 key-value
)转换为字典。尽管如此,' .'/3
默默地将这些列表转换为字典,而 get_dict/3
不会(使用 SWI-Prolog 8.2.2 测试)?
?- is_dict([key=value]).
false.
?- get_dict(key, [key=value], V).
ERROR: Type error: `dict' expected, found `[key=value]' (a list)
ERROR: In:
ERROR: [10] get_dict(key,[key=value],_25650)
ERROR: [9] <user>
?- get_dict(no_key, [key=value], V).
ERROR: Type error: `dict' expected, found `[key=value]' (a list)
ERROR: In:
ERROR: [10] get_dict(no_key,[key=value],_29084)
ERROR: [9] <user>
?- '.'([key:value], key, V).
V = value.
'.'([key=value], no_key, V).
ERROR: key `no_key' does not exist in _31746{key:value}
ERROR: In:
ERROR: [11] '$get_dict_ex'(no_key,_31802{key:value},_31798)
ERROR: [9] <user>
ERROR:
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.
这种行为的原因是什么?它在某处记录了吗?
我试过以下查询:
?- listing('.').
'$dicts':'.'(Data, Func, Value) :-
( '$get_dict_ex'(Func, Data, V0)
*-> Value=V0
; is_dict(Data, Tag)
-> eval_dict_function(Func, Tag, Data, Value)
; is_list(Data)
-> ( is_dict_func(Func)
-> dict_create(Dict, _, Data), % <== TRANSFORM LIST INTO DICT!!!
'$get_dict_ex'(Func, Dict, Value)
; '$type_error'(atom, Func)
)
; '$type_error'(dict, Data)
).
正如我们所见,谓词'.'
实际上是将列表转换为字典,然后再访问与键相关的值(我添加的代码注释)。除了代码清单,我没有找到任何关于这个事实的文档。
我在 SWI-Prolog 中进行了一些类型测试,偶然发现了字典和 Key=Value
术语列表之间的差异。或者更确切地说,我偶然发现了它们的相似之处。
根据SWI-Prolog manual dicts are "structures with named arguments" of the form Tag{Key1:Value1, Key2:Value2, ...}
. The manual mentions the predicates '.'/3
(section 4.2.1) and get_dict/3
(section 4.2.2) 从字典中提取值(其他谓词和功能符号故意省略)。谓词之间的区别在于,如果字典不包含所需的键,'.'/3
会引发异常,而 get_dict/3
会静默失败。然而,列表不是字典,即使有谓词将列表(键值关联的列表,例如 key:value
或 key-value
)转换为字典。尽管如此,' .'/3
默默地将这些列表转换为字典,而 get_dict/3
不会(使用 SWI-Prolog 8.2.2 测试)?
?- is_dict([key=value]).
false.
?- get_dict(key, [key=value], V).
ERROR: Type error: `dict' expected, found `[key=value]' (a list)
ERROR: In:
ERROR: [10] get_dict(key,[key=value],_25650)
ERROR: [9] <user>
?- get_dict(no_key, [key=value], V).
ERROR: Type error: `dict' expected, found `[key=value]' (a list)
ERROR: In:
ERROR: [10] get_dict(no_key,[key=value],_29084)
ERROR: [9] <user>
?- '.'([key:value], key, V).
V = value.
'.'([key=value], no_key, V).
ERROR: key `no_key' does not exist in _31746{key:value}
ERROR: In:
ERROR: [11] '$get_dict_ex'(no_key,_31802{key:value},_31798)
ERROR: [9] <user>
ERROR:
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.
这种行为的原因是什么?它在某处记录了吗?
我试过以下查询:
?- listing('.').
'$dicts':'.'(Data, Func, Value) :-
( '$get_dict_ex'(Func, Data, V0)
*-> Value=V0
; is_dict(Data, Tag)
-> eval_dict_function(Func, Tag, Data, Value)
; is_list(Data)
-> ( is_dict_func(Func)
-> dict_create(Dict, _, Data), % <== TRANSFORM LIST INTO DICT!!!
'$get_dict_ex'(Func, Dict, Value)
; '$type_error'(atom, Func)
)
; '$type_error'(dict, Data)
).
正如我们所见,谓词'.'
实际上是将列表转换为字典,然后再访问与键相关的值(我添加的代码注释)。除了代码清单,我没有找到任何关于这个事实的文档。