为什么''/ 3默默地将关联列表转换成字典?

问题描述

我在SWI-Prolog中进行了一些类型测试,偶然发现字典和Key=Value术语列表之间的差异。或更确切地说,我偶然发现了它们的相似性。

根据SWI-Prolog manual格是Tag{Key1:Value1,Key2:Value2,...}形式的“带有命名参数的结构”。手册中提到谓词'.'/3section 4.2.1)和get_dict/3section 4.2.2)以从字典中提取值(故意省略了其他谓词和功能符号)。谓词之间的区别在于,如果'.'/3失败时,如果字典不包含所需的键,则get_dict/3会引发异常。但是,即使有谓词将列表(键值关联,例如key:valuekey-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,_25650)
ERROR:    [9] <user>

?- get_dict(no_key,found `[key=value]' (a list)
ERROR: In:
ERROR:   [10] get_dict(no_key,_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,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)
    ).

如我们所见,谓词 '.'\3 在访问与键相关的值之前实际上将列表转换为字典(我添加的代码注释)。除了代码清单,我没有找到任何关于这个事实的文档。