假设我有一个谓词有时会给我多个输出。像这样-
foo(Number, Out) :- Number < 10, Out = less_than_ten.
foo(Number, Out) :- Number > 0, Out = more_than_zero.
如何记住Out
在另一个谓词中给出的foo
的所有值,并牢记它有时可以给出一个,有时也可以给出多个(例如,在列表中)?
编辑-不太确定我已经回答了我的问题,所以我会更具体。以上述谓词为例,我可以运行查询foo(5, Out).
,这将满足这两个规则,因此,如果我在SWI-prolog中运行它,我将得到-
?- foo(5, Out).
Out = less_than_ten
然后我可以输入一个分号以使序言回溯并寻找其他解决方案-
?- foo(5, Out).
Out = less_than_ten ;
Out = more_than_zero.
因此,如果我在另一个内部执行此谓词,给定Number = 5,如何获得Out的所有有效值?
答案 0 :(得分:3)
如果仅考虑整数,则可以选择使用CLP(FD)。然后您的谓词foo可能看起来像这样:
:- use_module(library(clpfd)).
foo(Nums) :-
Nums ins 1..9. % the numbers in the list Nums are 0 < X < 10
您可以使用此谓词来测试数字列表是否在所需范围内:
?- foo([1,2,3,4,5]).
yes
?- foo([0,1,2,3,4,5]).
no
?- foo([1,2,3,4,5,10]).
no
如果要使用它生成该范围内的整数列表,请确保Nums
是一个列表,以避免实例化错误。您可以在查询中添加一个目标长度/ 2作为前缀:
?- length(Nums,_), foo(Nums).
Nums = [] ? ; % <- no number
Nums = [_A], % <- one number
_A in 1..9 ? ;
Nums = [_A,_B], % <- two numbers
_A in 1..9,
_B in 1..9 ? ;
Nums = [_A,_B,_C], % <- three numbers
_A in 1..9,
_B in 1..9,
_C in 1..9 ?
.
.
.
这些答案包括剩余目标(有关详细信息,请参见CLP(FD) documentation)。如果要查看实际数字,则必须添加目标以标记列表:
?- length(Nums,_), foo(Nums), label(Nums).
Nums = [] ? ;
Nums = [1] ? ;
Nums = [2] ? ;
Nums = [3] ? ;
.
.
.
Nums = [1,1] ? ;
Nums = [1,2] ? ;
Nums = [1,3] ? ;
.
.
.
Nums = [9,9] ? ;
Nums = [1,1,1] ? ;
Nums = [1,1,2] ? ;
.
.
.
答案 1 :(得分:0)
首先,谓词可以成功或失败。
从技术上讲,并在序言standard
中进行了注明在Prolog中,您认为调用是执行。
执行是一系列试图满足目标的激活。
在Prolog中,您认为收益的意思是
如果BP激活成功,则更换当前的激活器 激活器true对CCG的激活,其激活描述于(7.8.1 .l)。
因此,通过将状态压入和弹出堆栈来传递值。
为简单起见,我将改用更通用的编程术语(调用,传递,参数),即使它们在技术上不是用于描述Prolog的正确术语。
要从foo
调用bar
,以便bar
可以将值传递给foo
,就像这样:
bar :-
foo(Passed_to_foo).
foo(Received_from_bar) :-
% Do something with Received_from_bar.
要扩展前一个并将一个值从foo
传递回bar
,将像这样:
bar :-
foo(Passed_to_foo,Received_from_foo).
foo(Received_from_bar,Passed_to_bar) :-
% Do something with Received_from_bar
% Generate/Compute Passed_to_bar
如果您不知道该参数是否将不包含任何项目,一个项目或一个或多个项目,那么您在考虑列表时是正确的,但是列表也可以同时执行全部三个操作。
要不传递任何值作为列表,只需传递一个空列表
[]
要在列表中传递一个值,只需将其放在列表中并传递列表
[first_value]
要传递多个值,只需将它们放在列表中并传递列表
[first_value, second_value, third_value, ... ]
由于值将始终位于列表中,因此只需使用良好的旧递归来处理列表中的项目即可。
基本情况
foo([],Result).
递归案例
foo([H|T],Result) :-
% Do something with head of list `H`
% Pass tail of list `T` back to foo for processing
foo(T,Result).
答案 2 :(得分:0)
刚刚找到了可以回答这个问题的谓词。 Prolog具有内置谓词bagof(Template, Goal, Bag)
,它将Template
谓词的Goal
自变量与Bag
自变量统一起来(不确定那是正确的Prolog语言!)。因此,在问题的示例中,使用bagof(Out, foo(5, Out), Outputs).
,这将与Out
合并Outputs
的解决方案列表。在SWI-prolog中运行查询:
4 ?- bagof(Out, foo(5, Out), Outputs).
Outputs = [less_than_ten, more_than_zero].
A useful guide for different ways to find all solutions to a goal.