Prolog 检查元素是否为列表的成员
基本上,我正在尝试创建标准成员谓词,以避免将模块加载到我的项目中 到目前为止,这是我的代码,但不幸的是它不起作用。我做错了什么?我甚至把切割操作符(!)放在那里,以确保它工作,但它不Prolog 检查元素是否为列表的成员,prolog,Prolog,基本上,我正在尝试创建标准成员谓词,以避免将模块加载到我的项目中 到目前为止,这是我的代码,但不幸的是它不起作用。我做错了什么?我甚至把切割操作符(!)放在那里,以确保它工作,但它不 /** * Checks if an element is part of a list * @param [H|T] List to evaluate * @param Elem Elem to check */ memberCheckSimple([], _):- !, fail. /* stop co
/**
* Checks if an element is part of a list
* @param [H|T] List to evaluate
* @param Elem Elem to check
*/
memberCheckSimple([], _):- !, fail. /* stop condition */
memberCheckSimple([H|T], Elem):-
Elem \= H, /* check if element equals head of list and negate it */
memberCheckSimple(T, Elem). /* loop */
memberCheckSimple(_, _). /* only gets here if Elem belongs to list */
谓词逻辑的一个主要问题是,它是基于失败的,并且您试图使成功成为无失败的默认值。这通常与你想要的逻辑相反。你希望它以成功为基础,也就是说,你希望建立事实和规则来描述什么是真实的 您可以按如下方式进行播放。您知道,如果元素位于列表的开头,那么它就是列表的一个元素。因此,以下是正确的:
memberCheckSimple([H|T], H). /* H is a member of [H|T] */
如果元素是列表尾部的成员,那么它也是列表的成员:
memberCheckSimple([_|T], H) :- memberCheckSimple(T, H).
这两条规则是你真正需要的。与上述规则之一不匹配的查询将失败,这正是您想要的
现在看看为什么基于失败的谓词不能正常工作,并且在失败案例中成功,这是因为以下规则:
memberCheckSimple(_, _).
这意味着任何事物都是任何事物的一部分。你必须承认,这似乎不符合逻辑(因为事实并非如此)。考虑到你先前的条款与削减:
memberCheckSimple([], _) :- !, fail.
如果第一个参数是空列表([]
),这将防止回溯到“universaltrue”子句,但如果其非空,则不会。例如,memberCheckSimple([a],b)
最终将通过与第二个子句匹配的路径失败,然后与第一个子句匹配。但是第一个子句中的删节并不能阻止memberCheckSimple([a],b)
对第三个子句进行回溯(和后续)。您可以通过执行跟踪
来观察这一点
要完成基于失败的方法(我将再次强调,这是解决问题的错误方法,并且还有其他问题,例如不相关),您还需要在第二条中删去:
memberCheckSimple([H|T], Elem) :-
Elem \= H, /* check if element equals head of list and negate it */
!,
memberCheckSimple(T, Elem). /* loop */
你在代码中的注释表明了一个强制性的思维过程。例如,你所谓的“循环”实际上是一个“递归”。另外,正如在另一条评论中提到的,参数顺序更自然地表示为元素后跟列表,因为您将其命名为“member”,而不是“contains”。注意,参数通常是:
member(El,Els)
memberCheckSimple(非元素,非列表)
succeeds@false是的,我知道,但是现在我所有的项目功能都是相反的,如果我现在试图改变它们,我会把事情搞得一团糟。所以,不妨让它保持一致(x)顺便说一句,我在stackoverflow上看到的每一篇序言都有你的身影!:p、 …但不幸的是,它不起作用。请解释一下你试过什么,什么不起作用。@潜伏者只要试一下,它就不会起作用了。memberCheckSimple([a,b,c],d)在应该说否时输出yes。