有人可以解释以下代码吗?我知道如果X离开Y则返回true,但是我不理解管道,下划线和R的内容。这是否意味着数组中除X和Y以外的所有其他元素?
left(X,Y,[X,Y|_]).
left(X,Y,[_|R]) :- left(X,Y,R).
答案 0 :(得分:3)
如果您不确定“实际”一词的含义,可以使用 write_canonical/1
获得其规范表示。
例如:
| ?- write_canonical([X,Y|_]). '.'(_16,'.'(_17,_18))
还有:
| ?- write_canonical([a,b|c]). '.'(a,'.'(b,c))
尤其是:
| ?- write_canonical([a|b]). '.'(a,b)
这向您显示[a|b]
是术语'.'(a,b)
,即具有函子.
和两个参数的术语。
要强调这一点:
| ?- [a|b] == '.'(a,b). yes
答案 1 :(得分:1)
@mat完全准确,完整地回答了最初的问题。但是,似乎您在注释中提出了一个更大的问题,即“谓词定义是什么意思?”
您的谓词left(X, Y, L)
定义了两个值X
和Y
与列表L
之间的关系。如果在列表X
中Y
的左边紧跟L
,则此谓词为true(查询成功)。
有两种方法可以做到这一点。一个是列表中的前两个元素是X
和Y
。因此,您的第一个子句为:
left(X, Y, [X,Y|_]).
这表示 X
在列表Y
中的[X,Y|_]
的紧后面。请注意,我们不在乎列表的末尾是什么,因为在这种情况下它无关紧要,因此我们使用_
。您可以在此处使用R
(或任何其他变量名称)并将其写为left(X, Y, [X,Y|R]).
,它将正常运行。但是,您会收到 singleton变量警告,因为您只使用了R
一次,而没有对其进行任何其他引用。出现警告是因为在某些情况下,这可能意味着您错误地执行了此操作。另请注意,[X,Y|_]
是至少两个元素的列表,因此,您不能只留下_
并写成[X,Y]
,而这是的列表em>恰好两个元素。
上面的子句并不是X
紧靠列表中Y
的唯一情况。如果它们不是列表中的前两个元素怎么办?您可以包含另一条规则,即如果列表末尾的X
紧跟Y
,则 X
紧靠列表Y
< / em>。这以及上面的基本情况将涵盖所有可能性,并给出left/3
的完整递归定义:
left(X, Y, [_|R]) :- left(X, Y, R).
此处,列表为[_|R]
,列表的末尾为R
。
答案 2 :(得分:0)
这是关于模式匹配的内容,也是关于Prolog的执行机制的信息,该机制建立在模式匹配的周围。
考虑一下:
1 ?- [user].
|: prove(T):- T = left(X,Y,[X,Y|_]).
|: prove(T):- T = left(X,Y,[_|R]), prove( left(X,Y,R) ).
|:
|: ^Z
true.
此处prove/1
模拟Prolog的工作原理,证明对您的T
谓词的查询left/3
。
通过将查询与规则的头部匹配,并在所产生的替换下证明该规则的主体来证明查询。
自然会立即证明一个空的身体。
{prove(T):- T = left(X,Y,[X,Y|_]).
编码为“ match 第一个规则的头。没有正文,因此如果匹配成功,我们将完成。” >
prove(T):- T = left(X,Y,[_|R]), prove( left(X,Y,R) ).
进行编码,“ match 匹配第二条规则的头部,如果成功,则在结果替换(隐式)下证明其主体”。
Prolog的统一=
在根据要匹配的内容实例化在匹配项内找到的任何逻辑变量的同时执行模式匹配。
因此,我们观察到
2 ?- prove( left( a,b,[x,a,b,c])).
true ;
false.
3 ?- prove( left( a,b,[x,a,j,b,c])).
false.
4 ?- prove( left( a,b,[x,a,b,a,b,c])).
true ;
true ;
false.
5 ?- prove( left( a,B,[x,a,b,a,b,c])).
B = b ;
B = b ;
false.
6 ?- prove( left( b,C,[x,a,b,a,b,c])).
C = a ;
C = c ;
false.
;
是我们按下以从Prolog请求下一个解决方案的键(在Prolog暂停期间,等待我们的命令)。