Prolog:具有真假价值

时间:2017-03-15 20:16:27

标签: list prolog

我正在学习使用SWI Prolog,我正在学习使用列表。一个小练习是检查元素是否在列表中。这就是我得到的:

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

第一种情况符合预期:

?- member(a,[b,a]).
true.

但是第二个没有,因为有些回溯似乎出现了:

?- member(a,[a,b]).
true ;
false.

我怎样才能防止这种情况发生,即让Prolog只返回 true ? (我不想忽视错误。)

4 个答案:

答案 0 :(得分:4)

server { listen 80; listen [::]:80; root /var/www/example.com/html/; index index.php index.html; server_name example.com www.example.com; location / { try_files $uri $uri/ =404; } # deny accessing php files for the /assets directory location ~ ^/assets/.*\.php$ { deny all; } # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # location ~ \.php$ { include snippets/fastcgi-php.conf; # With php7.0-cgi alone: # fastcgi_pass 127.0.0.1:9000; # With php7.0-fpm: fastcgi_pass unix:/run/php/php7.0-fpm.sock; } } 是标准的Prolog谓词。你应该为别人命名。标准谓词与您显示的行为相同。

查询时:

member/2

Prolog发现?- member(a, [a,b]). true ; false. 匹配第一个元素并成功。列表中还有更多内容需要检查,以便提示您提供更多信息。按a说"是的,请检查更多"。当它发生时,它不再找到;成员,因此产生a(在GNU Prolog中,它会说false)。

你可以通过以下两种方式消除它:

  • 未按no但按Enter键,或
  • 使用;once/1,或
  • 您可以更改谓词以包含第一个子句中的剪切,但这是一个坏主意,因为它在一般情况下不会起作用:once(member(a, [a,b]))只会返回member(X, [a,b])然后停止。

答案 1 :(得分:3)

根据memberd/2 | SICStus提供的library(reif)使用SWI,在许多情况下您会获得确定性:

?- memberd(a, [a,b]).
true.

?- memberd(a, [a,a]).
true.

?- memberd(a, [a,X]).
true.

?- memberd(a, [a|Xs]).
true.

将此与member/2

进行比较
?- member(a, [a,b]).
   true
;  false.              % leftover choicepoint

?- member(a, [a,a]).
   true
;  true.               % redundant solution

?- member(a, [a,X]).
  true
; X = a.               % redundant solution

?- member(a, [a|Xs]).
   true
;  Xs = [a|_A]         % redundant answer
;  Xs = [_A, a|_B]     % redundant answer
;  Xs = [_A, _B, a|_C] % redundant answer
...

memberd/2的实施仍然会在必要时产生不同的答案

?- memberd(a, [X,Y]).
   X = a
;  Y = a,
   dif(X, a)
;  false.

即使在这种情况下,memberd/2也避免了member/2

的冗余
?- member(a, [X,Y]).
   X = a
;  Y = a.        % partially redundant

这两个答案部分冗余:X = a, Y = a由两者描述!

?- member(a, [X,Y]), X = a, Y = a.
   X = Y, Y = a
;  X = Y, Y = a.    % redundant solution

答案 2 :(得分:0)

请注意,由于member(X,[X|_])member(X,[_|T])统一,因此任何查询都会与两个子句统一。你需要相互排斥的条款。由于prolog cut会打破可逆性(如前所述),还有另一种选择:

member(X,[X|_]).
member(X,[Y|T]):- X \== Y, member[X|T].

答案 3 :(得分:0)

另一个答案是好的,但也许重要的是要在教科书中添加member/2完全正确,因为它使用模式匹配和统一它可以做更多有趣的事情......

?- member(a(X), [a(1), b(2), c(3), a(4), b(5), a(6)]).
X = 1 ;
X = 4 ;
X = 6.

还有memberchk/2仅用于测试会员资格。另一个答案也解释了如何实施。

看起来两者的目的不一样(为什么要两者都这样?)