Почему ‘.’ / 3 автоматически преобразует ассоциативный список в dict?

#dictionary #swi-prolog

#словарь #swi-prolog

Вопрос:

Я проводил некоторое тестирование типов в SWI-Prolog и наткнулся на различия между dicts и list of Key=Value terms . Или, скорее, я наткнулся на их сходство.

Согласно руководству SWI-Prolog, dicts — это «структуры с именованными аргументами» формы Tag{Key1:Value1, Key2:Value2, ...} . В руководстве упоминаются предикаты '.'/3 (раздел 4.2.1) и get_dict/3 (раздел 4.2.2) для извлечения значений из dict (другие предикаты и функциональные обозначения намеренно опущены). Разница между предикатами заключается в том, что '.'/3 возникает исключение, если dict не содержит нужного ключа, в то время get_dict/3 как происходит сбой без предупреждения. Однако списки не являются dict, даже если есть предикаты, преобразующие списки (ассоциаций ключ-значение, например, key:value или key-value ) в dict . Тем не менее, ' .'/3 автоматически преобразует эти списки в dict, в то время 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.

  

В чем причина такого поведения? Это где-нибудь задокументировано?

Ответ №1:

Я попробовал следующий запрос:

 ?- 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)
    ).
  

Как мы можем видеть, предикат '.'3 фактически преобразует список в словарь, прежде чем получить доступ к значению, связанному с ключом (комментарий к коду, добавленный мной). За исключением списка кода, я не нашел никакой документации по этому факту.