2010-11-09 5 views
13

Итак, оператор univ. Я не совсем понимаю это.Prolog GNU - 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?

+1

+1 за вопрос, как переписать без univ. Кстати, существуют функции предикатов ISO/3 и arg/3, которые могли бы выполнять эту работу в некоторых случаях и должны быть предпочтительными, но я не уверен, что они всегда могут быть использованы. – Kaarel

+0

@ Kaarel, +1. Обновлен мой ответ. –

ответ

14

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 предикат должен быть предпочтительным.)

Редактировать: Kaarel является правильным, 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 
+3

Хороший ответ.Просто для пояснения: оператор Univ объединяет термин слева со списком справа, так что глава списка является функтором, а хвост списка - аргументами. –

+0

Хмм интересно. Благодаря! – Matt

+0

@larsmans: Вы заставляете «H» быть атомом. Таким образом, вы предотвращаете частичное применение! См. Решение @Cookie Monster. – false

2

наиболее подходящим переписан на мой взгляд, было бы:

bar([H|_], Item) :- call(H, Item). 

call/n еще не являются частью основного стандарта ISO, но они могут becom e в ближайшем будущем (*). Многие системы Prolog уже поддерживают их.

Существует одна причина, почему 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 

С наилучшими пожеланиями

(*)
Проект технических опечаток 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

+1

О «Кто его придумал»: фактический первый письменный источник, о котором я знаю, представляет собой проект предложенного стандарта для Prolog Evaluable Predicates_ Ричарда О'Кифа, который был впервые публично объявлен 1984-07-25. Вы обнаружите, что прекурсор ограничен некоторым не полностью определенным видом лямбда, но ** не разрешает частичное применение ** в Mycroft, O'Keefe _A полиморфный тип системы для Prolog_, AI Journal, август 1984 года. – false

+1

Я предполагаю, что это соответствует (1) Алан Мыкрофт и я изобрели call/N вместе. Никто не участвовал ». из РК найден во второй ссылке? –

+0

Каким-то образом. Но не совсем. Есть и другие утверждения, предполагающие, что 'call/N' уже был изобретен в этой статье. – false

 Смежные вопросы

  • Нет связанных вопросов^_^