3

根据我的理解,声明式范式表明什么对解决方案很重要,而不是如何达到解决方案,但是习惯于程序化思考,我经常混淆......

所以解决方案是这个:

mymember(X, [X|_]).
mymember(X,[_|T]) :- mymember(X,T).

这是我对这个简单程序的声明式解释:

1) X 属于该列表,如果 X 是该列表的头为 TRUE(如果列表的头元素与我知道是否在列表中的 X 元素统一)

2)如果第一个事实不正确(X 不与第一个列表元素统一),则程序尝试执行第二个规则(也许在这里我有一些解释问题)。这条规则说:如果规则的主体为真,则头部为真)

规则的负责人说:X属于列表的TAIL(我使用匿名变量使用_字符表示不关心列表的第一个元素)

所以这条规则说:如果 X 元素属于列表的尾部为 TRUE,则 X 元素属于没有头部的列表为 TRUE

这是对该程序的正确声明和逻辑解释还是我遗漏了什么?

4

3 回答 3

2

您将它们阅读为异或,但它们实际上是包容或。1) 和 2) 都是正确的,减去连接词“如果第一个事实不正确”。对于 2) 保持,1) 没有必要为假。换句话说,X既是列表的头部又出现在列表的尾部(例如mymember(a, [a, b, a]).

编辑:回复您的评论。

这里有一个语言障碍问题,所以让我试着用是和否来回答你的问题。

是的,使用;产生另一个答案是 Prolog 能够计算替代答案的证据。在某种意义上,;手动触发回溯,但在另一种意义上,Prolog 会询问您这是否是您想要的答案,然后您可以说“是”或“否”。当你说;你是在告诉 Prolog 时,本质上,“这不是正确的答案”。但这不是触发回溯的唯一方法;事实上,大多数时候你根本不会手动触发它。

例如,让我们看一下:

even_member(X, L) :- member(X, L), 0 is X mod 2.

?- even_member(X, [1,5,17,23,4,19]).
X = 4 ;
false.

所以在这里我定义了一个谓词,声明式地说,如果 X 是 L 的成员并且 X mod 2 = 0,则 X 是 L 的 even_member。当我使用谓词时,我们得到了答案X = 4。然后我们按着;说,这不是正确的答案,Prolog 说没有更多的答案。但是在内部,member(X, L) 在找到满足谓词第二部分的元素之前回溯了 5 次——换句话说,该语句0 is X mod 2告诉 Prolog 1、5、17 和 23 以同样的方式“错误”我们通过;交互按下来做到这一点。当我们说我们想要另一个答案时,我们使用了相同的机器,所以 Prolog 回到 member(X, L),找到 19,然后发现 19 不能被 2 整除并放弃。

Prolog 回溯了六次,其中五次只是为了得到一个答案。我们只要求它回溯一次,碰巧这是最后的可能性,所以它没有再次回溯。

于 2013-03-18T16:20:00.837 回答
2

让我尝试:

mymember(X, [X|_]).

如果 X 是列表的第一个元素,则 X 是列表的成员

mymember(X,[_|T]) :- mymember(X,T).

如果 X 是列表其余部分的成员,则 X 是列表的成员。

假设我给你一堆(纸质)程序员简历并说“看看其中有没有懂 Prolog 的程序员”

你做什么工作?你看看最上面的简历。如果那个程序员知道 Prolog,你就完成了。

如果不是,那么只有这样一份简历的唯一方法就是它是否在堆栈的其余部分中。

于 2013-03-19T02:08:16.847 回答
0

第 2 点)不成立:Prolog 将尝试搜索解决方案的每个规则。

但它将遵循严格指定的顺序在您的数据库中搜索,从而导致对解决方案空间的深度优先搜索。

我会读

如果 X 是第一个元素(即统一头部,第 1 条),或者是尾部的成员(第 2 条),则 X 是列表的成员。

于 2013-03-18T16:23:43.167 回答