Prolog新手在这里谁想知道为什么这些规则不能自立,如果我想知道某些东西是否是列表的成员。
member(X, [X|_]).
member(X, [_|Y]) :- member(X,Y).
如果我要求以下规则:
member(will, [anna, eddie, pat, will, marjorie, donna]).
我知道,但如果我删除:
member(X, [X|_]).
刚离开第二条规则,我就是假的。如果第二条规则规定“如果X是列表尾部的成员,则X是列表的成员”,为什么会这样呢?
“will”是此列表尾部的成员。
而且,为什么可以
member(X, [X|_]).
单独告诉我什么时候X是列表的头部(第二个规则不能)?
谢谢。
答案 0 :(得分:5)
如果您只有member(X, [X|_]).
并执行此查询:member(will, [will,anna]).
您将获得true.
,因为根据您的规则,X将是列表的头部。
但是如果你只有那条规则并执行member(anna, [will,anna]).
,那么你就会得到错误,因为安娜不是你名单的负责人。
让我们看看你的第二条规则。
您将程序创建为member(X, [_|Y]) :- member(X,Y).
您执行查询member(will, [anna, eddie, pat, will, marjorie, donna]).
这就是Prolog看到的:
获取列表并移除头部。对列表的其余部分执行相同操作,直到尾部为空。
您获得false.
,因为列表中没有任何元素。
您的问题是您不会检查X是否是您列表的成员。您也可以将该规则重命名为removehead(X,[_|Y]):-removehead(X,Y).
答案 1 :(得分:4)
刚离开第二条规则,我就错了。
没有基本情况的规则失败的原因是,当列表归结为单个项目时,当列表变空时,没有规则与其右侧统一。
您可以使用较短的列表在一张纸上播放:
member(will, [anna, will])
开始。anna
统一到_
,并将[will]
保持在Y
will
统一到_
并将[]
保持在Y
member(will, [])
规则不再与其统一,因为member(X, [_|Y])
要求第二个参数是至少包含一个项目的列表。false
返回顶层调用者。而且,为什么
member(X, [X|_]).
可以独立并告诉我什么时候X是列表的头部
这是因为规则立即成功,而不必与右边的任何其他规则统一。
通常,当您处理数据结构的递归处理时,您需要寻找两件事:
单独处理基础案例有时会给你带来结果;单独处理还原步骤永远不会给你正确的结果,因为它可以做所有的还原工作。
答案 2 :(得分:2)
member(X, [_|Y])
(1)仅匹配[_|Y]
形式的列表,(2)从不查看实际元素。尝试跟踪执行:
?- trace.
true.
[trace] ?- member(foo, [foo, bar]).
Call: (6) member(foo, [foo, bar]) ? creep
Call: (7) member(foo, [bar]) ? creep
Call: (8) member(foo, []) ? creep
Fail: (8) member(foo, []) ? creep
Fail: (7) member(foo, [bar]) ? creep
Fail: (6) member(foo, [foo, bar]) ? creep
false.
正如预期的那样,你的member
版本只是跳过元素,因为它只想看尾部,直到它碰到[]
,与头部的模式不匹配。
另一个版本member(X, [X|_])
可以匹配每个定义的头。它会查看头部并将其与您正在寻找的项目统一起来。