Как мне вернуть список в Прологе? - PullRequest
5 голосов
/ 26 мая 2011

Допустим, у меня есть следующие факты:

parent(bob, sam). %bob is sam's parent
parent(sara, sam). %sara is sam's parent

Я хотел выяснить, кто были sam родителями, и вернуть их в список и таким образом использовать:

list_parents(P, L) :- findall(Parent, parent(Parent, P), L).

Теперь я хочу задать тот же вопрос, но с одним аргументом как таковым:

findParents(sam).

Я пытался:

findParents(Name) :- list_parents(Name, L).

но таким образом, Прологпросто отвечает "True".

Ответы [ 3 ]

8 голосов
/ 27 мая 2011

С прологом дело в том, что он немного отличается от большинства языков (преуменьшение, если таковой был каждый):

  • Все переменные имеют локальную область видимости.

  • Переменные значения инвариантны после привязки (унифицировано), если только обратное отслеживание не отменяет их.

  • Предикаты не возвращают значение в общепринятом смысле.Они либо успешны, либо терпят неудачу.

  • Чтобы получить значение от тестирования предиката, вы оцениваете предикат, передавая ему что-то из предиката.Неважно, передадите ли вы ему переменную или связанное значение: вызываемый предикат будет успешным или будет иметь значение, если то, что имеет вызывающий, объединяется с тем, что вы передали.Если вы передали переменную, и вызываемый предикат объединяет ее с не переменным значением, ваша переменная привязывается к этому значению.Подумайте об этом (несколько), как если бы у вас был процедурный язык, где каждая функция возвращала bool, а все значения параметров передавались по ссылке.

То, что вы пытались сработать:

findParents(Name) :- list_parents(Name, L).

Переменная L была объединена с (была связана) со списком, возвращаемым findall/3.И затем он вышел из области видимости.

Если вы хотите на самом деле сделать что-то с этим возвращенным (связанным) значением, вам нужно иметь дело с ним там, где оно находится в области действия, или объединить егозначение с чем-то, с чем был вызван этот предикат и, таким образом, передать его в стек вызовов.Или вы можете добавить его в базу данных фактов и сохранить на потом.

Способ, которым работает пролог, заключается в том, что корневой предикат, используемый для запуска вашей "программы", определяет дерево поиска в терминах предикатов в вашембаза данных.Затем «движок» Пролога выполняет поиск дерева в глубину, слева направо.Ваш предикат успешно выполняется, когда движок попадает в конечный узел дерева поиска, которое вы определили.Возврат к вашему предикату заставляет движок искать следующее решение в дереве поиска.

В результате все, что вы хотите сделать постоянно, должно происходить как побочный эффект пролога «движок»оценивая предикат.Например, print() всегда успешно выполняется только один раз (когда вы вводите поле) ... и в качестве побочного эффекта печатается все, что вы просили его напечатать.Возврат в печать не «отменяет» печать, но print() снова не удается.

2 голосов
/ 22 августа 2016

Библиотека func предоставляет синтаксис для функций с возвращаемыми значениями в SWI-Prolog.В этом примере вы можете напечатать всех родителей sam, написав writeln(list_parents $ sam):

:- initialization(main).
:- use_module(library(func)).

main :- writeln(list_parents $ sam).

list_parents(P, L) :- findall(Parent, parent(Parent, P), L).
parent(bob, sam). %bob is sam's parent
parent(sara, sam). %sara is sam's parent

Аналогично, вы можете определить функцию с несколькими параметрами, такими как этот:

% return a item at an index in a list.
nth0((Index,List),ToReturn) :-
    nth0(Index,List,ToReturn).

... а затем используйте его так:

example :-
    ListIndex = (nth0 $(0,[1,2,3,4])), %returns 1, which is the first item in this list
    writeln(ListIndex).
2 голосов
/ 26 мая 2011

вы можете распечатать список, если хотите, чтобы его видел только пользователь что-то вроде:

findParents(Name):-
   list_parents(Name,L),
   print(L).

но это точно не возвращается. помните, в прологе нет функций и, следовательно, нет «возвращаемых значений». Вы можете смоделировать функцию, написав foo (Args, Return), но вы всегда можете назвать ее как foo (X, sam) - иногда она выдаст то, что вы хотите, иногда нет, иногда вылетает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...