2016-03-09 9 views
1

Я изучаю Prolog и я следил за this tutorial for graphs. Вот мой код:Написание предиката Prolog для предоставления параметров по умолчанию другому предикату

path(X, Y, Length, [X,Y], _) :- 
    connect(X, Y, Length). 
path(X, Y, Length, [X|P], V) :- 
    \+ member(X, V), 
    connect(X, Z, Length1), 
    path(Z, Y, Length2, P, [X|V]), 
    Length is Length1 + Length2. 

Чтобы использовать это, я называю

?- path(a, f, Length, Path, []). 

Однако, я хотел бы сократить его:

?- path(a, f, Length, Path). 

Но я не могу получить по умолчанию параметры работы.

+0

См. ['This definition'] (http://stackoverflow.com/q/30328433). – false

+0

@false Я изначально связал этот вопрос; однако, если кромки имеют значения, связанные с ними, это всего лишь половина ответа. Я хочу использовать эту возможность, чтобы спросить: есть ли там одно место, где можно найти весь отличный код, написанный вами (и некоторые из замечательных ответов)? В настоящее время он разбросан вокруг тега Prolog, и у меня часто возникают проблемы с его поиском, хотя я знаю, что это где-то там ... –

+0

@Boris: см. Мой профиль и [это место] (http: //www.complang.tuwien .ac.at/Ulrich/Пролог-inedit /). Я планирую включить их в более полную форму, но это намного больше, чем кажется, потому что я стараюсь соответствовать всем * возможным * возможным. – false

ответ

6

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

path(X, Y, Length, Path) :- 
    path(X, Y, Length, Path, []). 

В Прологе предикаты всегда упоминается с Name/Arity потому что то же самое имя, но разные Арность делает их два отдельных предиката. Итак, теперь ваша программа будет иметь как path/4, так и path/5.

Что касается именования: если оба предиката являются частью вашего интерфейса, они должны иметь то же имя. Многие примеры в стандартных библиотеках Prolog, например format/1, format/2, format/3.

Если, однако, рабочий предикат предназначен только для использования в качестве вспомогательного предиката, обычно вы даете ему суффикс. Для того, чтобы использовать что-то простое, как list_max/2:

list_max([X|Xs], Max) :- 
    list_max_SUFFIX(Xs, X, Max). 

Я видел код, где SUFFIX просто подчеркивание: list_max_/3 (а вы продолжайте добавлять подчеркивания для более помощника предикаты вниз один и тот же предикат родословная); или, подчеркивание + число: list_max_1/3 (и вы увеличиваете число); или, _aux + дополнительный номер, если у вас есть больше: list_max_aux/3. Использование символа подчеркивания +:

list_max_1([], Max, Max). 
list_max_1([X|Xs], Max0, Max) :- 
    compare(Order, X, Max0), 
    list_max_2(Order, X, Max0, Xs, Max). 

list_max_2(<, _, Max0, Xs, Max) :- list_max_1(Xs, Max0, Max). 
list_max_2(=, _, Max0, Xs, Max) :- list_max_1(Xs, Max0, Max). 
list_max_2(>, X, _, Xs, Max) :- list_max_1(Xs, X, Max). 

Но подождите, есть еще. Если вы используете схему именования для своих предикатов, где имя представляет аргументы, вы получаете, например, setup_call_cleanup/3 и call_cleanup/2, определяемые как setup_call_cleanup(true, Goal, Cleanup). С помощью этой схемы именования вы назовете свои «дорожные» предикаты, возможно, from_to_length_path/4 и from_to_length_path_acc/5. Я нахожу эту схему именования приятной, потому что она самодокументирована, но, как показывает этот пример, она может стать чрезмерной, если в вашем предикате слишком много аргументов.

+3

s (X) для вашего подробного ответа! – repeat

+1

@repeat По-видимому, мне нечего делать, и больше нигде не должно быть. –

+1

Там ** есть ** ничего лучше делать и больше нигде не быть :) – repeat