我正在学习使用SWI Prolog,我正在学习使用列表。一个小练习是检查元素是否在列表中。这就是我得到的:
member(X,[X|_]).
member(X,[_|T]):-member[X|T].
第一种情况符合预期:
?- member(a,[b,a]).
true.
但是第二个没有,因为有些回溯似乎出现了:
?- member(a,[a,b]).
true ;
false.
我怎样才能防止这种情况发生,即让Prolog只返回 true ? (我不想忽视错误。)
答案 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
仅用于测试会员资格。另一个答案也解释了如何实施。
看起来两者的目的不一样(为什么要两者都这样?)