#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
фактически преобразует список в словарь, прежде чем получить доступ к значению, связанному с ключом (комментарий к коду, добавленный мной). За исключением списка кода, я не нашел никакой документации по этому факту.