编写 Prolog 谓词以向另一个谓词提供默认参数
Writing a Prolog predicate to supply default parameters to another predicate
我正在学习 Prolog 并且我跟进了
this tutorial for graphs。
这是我的代码:
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).
但我无法使用默认参数。
非常简单:只需定义一个同名的谓词,调用谓词来完成工作:
path(X, Y, Length, Path) :-
path(X, Y, Length, Path, []).
在 Prolog 中,谓词总是用 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
, and call_cleanup/2
,定义为 setup_call_cleanup(true, Goal, Cleanup)
。使用此命名方案,您可以将 "path" 谓词称为 from_to_length_path/4
和 from_to_length_path_acc/5
。我发现这个命名方案很好,因为它是自我记录的,但正如这个例子所示,如果你的谓词有太多参数,它可能会变得过多。
我正在学习 Prolog 并且我跟进了 this tutorial for graphs。 这是我的代码:
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).
但我无法使用默认参数。
非常简单:只需定义一个同名的谓词,调用谓词来完成工作:
path(X, Y, Length, Path) :-
path(X, Y, Length, Path, []).
在 Prolog 中,谓词总是用 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
, and call_cleanup/2
,定义为 setup_call_cleanup(true, Goal, Cleanup)
。使用此命名方案,您可以将 "path" 谓词称为 from_to_length_path/4
和 from_to_length_path_acc/5
。我发现这个命名方案很好,因为它是自我记录的,但正如这个例子所示,如果你的谓词有太多参数,它可能会变得过多。