В SWI Prolog:
Допускаются точные дубликаты пунктов:
a(1).
a(1).
?- a(X).
X = 1 ;
X = 1.
или даже:
c :- format("Hello from first c!").
c :- format("Hello from second c!").
Hello from first c!
true ;
Hello from second c!
true.
В более общем смысле, так это пункты с одинаковыми полностью заземленными головками, но разными телами:
b(1) :- format("Hello from first b!").
b(1) :- format("Hello from second b!").
?- b(1).
Hello from first b!
true ;
Hello from second b!
true.
Предложения с одинаковыми не заземленными головками кажутся более разумными:
p(X) :- format("Yup, this is p(~w)",X).
p(X) :- format("Yup, this is also p(~w)",X).
p(X) :- format("You think you can get rid of good old p(~w) just like that?",X).
?- p('homer simpson').
Yup, this is p(homer simpson)
true ;
Yup, this is also p(homer simpson)
true ;
You think you can get rid of good old p(homer simpson) just like that?
true.
?- p(X).
Yup, this is p(_4782)
true ;
Yup, this is also p(_4782)
true ;
You think you can get rid of good old p(_4782) just like that?
true.
Это охватывает разумный случай пунктов с охраняемым телом:
p(X) :- X < 0, format("It's less than 0: ~w", X).
p(X) :- X =:= 0, format("It's exactly 0: ~w", X).
p(X) :- X > 0, format("It's larger than 0: ~w", X).
Если подумать ... мы уже сталкиваемся с окончательным случаем во встроенном repeat
:
?- repeat.
true ;
true ;
true ;
true ;
…
Или можно легко создать промежуточный регистр:
h :- member(_,[1,2,3]).
?- h.
true ;
true ;
true.
Каким-то образом учебники затмевают тот факт, что предикаты имеют дополнительную семантику: они могут быть не только false
или true
для любых заданных аргументов основания, но на самом деле они могут быть true(n)
- «истинно n раз, n ≥ 0» .
С теоретической точки зрения это сомнительно, по крайней мере для vanilla classic logi c.
С другой стороны, это полезно из вычислений общая точка зрения для:
- Побочные эффекты (скорее для вывода, чем для ввода, и довольно незначительно).
- Контроль вычислений (то есть
repeat
).
Существуют ли другие варианты использования?
Я действительно считаю, что компилятор должен отмечать регистры без переменных, такие как a/1
, c/0
, b/1
выше, как ошибки (легко обнаруживаемые), и даже repeat/0
должно иметь значение: repeat(Count)
. Все, что успешно вернет , НЕ ДОЛЖНО * повторить успешно в том же контексте на тех же основополагающих аргументах. У него такое же мягкое чувство неактуальности, как у a(X) :- b(Y). b(Z).
Бррр!