В чем разница между целями без call/2 и без call/2 в прологе?

В чем разница между этими двумя целями?

foo(A) :- A, !, fail.
foo(A).
foo(A) :- call(A), !, fail.
foo(A).

Кажется, они ведут себя одинаково? Какова цель call/1 и есть ли пример, когда это имеет значение?


person kentrid    schedule 19.10.2020    source источник
comment
Это может иметь значение, если у вас есть модули в вашей программе. Однако я не уверен, как GNU-Prolog работает с модулями. Как бы то ни было, ваш foo/1 является метапредикатом. Возможно, вы могли бы прочитать о мета-предикатах в документации по используемому вами Прологу (GNU-Prolog?) и сообщить нам, есть ли что-нибудь интересное.   -  person TA_intern    schedule 20.10.2020
comment
Хорошо, я посмотрел. GNU-Prolog не поддерживает модули. Другие прологи делают.   -  person TA_intern    schedule 20.10.2020


Ответы (1)


Нет никакой разницы в выходном коде WAM, сгенерированном этими фрагментами кода, о чем свидетельствует выдача

gplc -w snippet1.pl
gplc -w snippet2.pl

и проверка сгенерированного файла wbc (где snippetN.pl содержит либо образец кода). Так что, похоже, это выбор программиста, какой из них использовать. Может быть полезно использовать call/1 из соображений переносимости.

Однако вспомните о существовании call/N с N > 1, что полезно, если вы хотите вызвать цель, у которой есть аргументы.

Для любопытных, это сгенерированный файл wam: predicate(foo/1,1,static,private,monofile,global,2).

clause(:-(foo(A),','(A,','(!,fail))),[
    allocate(1),
    get_variable(y(0),1),
    put_atom(foo,1),
    put_integer(1,2),
    put_atom(true,3),
    call(('$call')/4),
    cut(y(0)),
    fail]).


clause(foo(_),[
    proceed]).

Единственное отличие заключается в заголовке предложения, которое в другом фрагменте гласит:

clause(:-(foo(A),','(call(A),','(!,fail))),[
person gusbro    schedule 19.10.2020
comment
Спасибо. Итак, в каком случае call/1 полезен? - person kentrid; 19.10.2020
comment
Я никогда не использую ваш первый фрагмент A, но call(A). Так что для меня полезно call/1, так как я как программист предпочитаю использовать последнее. call/1 также является частью стандарта ISO, поэтому его может обеспечить любой соответствующий процессор. Я не думаю, что просто выпуск A является стандартом ISO. Я думаю, что более портативно использовать call(A), а не просто A. - person gusbro; 19.10.2020
comment
Есть ли пример, где call/1 полезен (а не call/N)? - person kentrid; 19.10.2020
comment
Портативность - это пример, который я вам предложил - person gusbro; 19.10.2020
comment
Это ловушка против опечаток, например, использование заглавной буквы в вызове предиката в теле предложения. Использование call/1 делает вещи однозначными. - person peter.cyc; 07.11.2020
comment
@peter.cyc: опечатки обычно обнаруживаются с помощью lint, который выдает предупреждение об одноэлементной переменной, которое вы всегда должны проверять. - person gusbro; 08.11.2020