Пролог GNU - оператор Univ? Объяснение этого
-
29-09-2019 - |
Вопрос
Итак, оператор Univ. Я не совсем понимаю.
Например:
foo(PredList,[H|_]) :- bar(PredList,H).
foo(PredList,[_|T]) :- foo(PredList,T),!.
bar([H|_],Item) :- G =.. [H,Item],G.
bar([_|T],Item) :- bar(T,Item).
Что это делает? Это выглядит, чтобы увидеть, правда ли другой предикат. Я не понимаю, что делает "..".
Как бы вы переписали это без оператора Univ?
Решение
Univ (=..
) разбивает термин в список избирателей или строит термин из такого списка. Пытаться:
?- f(x,y) =.. L.
L = [f, x, y].
?- f(x,y,z) =.. [f|Args].
Args = [x, y, z].
?- Term =.. [g,x,y].
Term = g(x, y).
bar
кажется, называет каждый предикат в PredList
на Item
, с foo
возвращение к Item
с. (Использование переменной в качестве предиката не портативно; call
Предупреждение должно быть предпочтительным.)
Редактировать: Каарел прав, Univ может быть заменен на functor/3
и arg/3
, следующее:
bar([H|_],Item) :-
functor(Goal,H,1), % unifies Goal with H(_)
arg(1,Goal,Item), % unifies first argument of Goal with Item
call(Goal). % use this for portability
Другие советы
На мой взгляд, наиболее подходящим переписыванием было:
bar( [H|_], Item ) :- call(H, Item).
call/n
еще не являются частью основного стандарта ISO, но они могут стать в ближайшем будущем (*). Многие системы пролог уже поддерживают их.
Есть одна причина, почему call/n
должен быть предпочтительнее простых (=..)/2
и functor/3
+ arg/3
решения. То call/n
Решение способно обрабатывать закрытие (**).
С простым (=..)/2
и functor/3
+ arg/3
решение, которое можно вызвать bar/2
Только с атомами в первом аргументе. Например:
p1(1).
p2(2).
?- bar( [p1, p2], 1 ).
Yes
?- bar( [p1, p2], 2 ).
Yes
?- bar( [p1, p2], 3 ).
No
С закрытыми мы не ограничены атомами, и мы могли бы сохранить некоторые усилия по кодированию. Например, мы можем сделать следующее напрямую:
?- bar( [=(1), =(2)], 1 ).
Yes
?- bar( [=(1), =(2)], 2 ).
Yes
?- bar( [=(1), =(2)], 3 ).
No
Наилучшие пожелания
(*)
Проект технического Corrigendum 2
http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#call
(**)
Кто это изобрел?: call/n
Предикаты
http://www.complang.tuwien.ac.at/ulrich/prolog-inedit/naish.html