我是Prolog的新手,我无法理解这段代码。你会如何阅读这4个条款?他们在做什么?
a([]).
a([_|L]):-b(L).
b([_]).
b([_|L]):-a(L).
谢谢。
答案 0 :(得分:1)
参数模式很重要:
a)清单显然是一个反击,因为我们从不考虑内容。
b)只是一个建议:将逻辑读作制作,或作为DCG
a-->[];[_],b.
b-->[_];[_],a.
被调用 - 例如
?- phrase(a, [w,h,a,t]).
答案 1 :(得分:1)
正如@repeat在评论中建议的那样,运行一般查询,这就是你得到的:
| ?- a(Xs).
Xs = [] ? ;
Xs = [_,_] ? ;
Xs = [_,_] ? ;
Xs = [_,_,_,_] ? ;
Xs = [_,_,_,_] ? ;
Xs = [_,_,_,_,_,_] ? ;
Xs = [_,_,_,_,_,_] ? ;
...
和
| ?- b(Xs).
Xs = [_] ? ;
Xs = [_] ? ;
Xs = [_,_,_] ? ;
Xs = [_,_,_] ? ;
Xs = [_,_,_,_,_] ? ;
Xs = [_,_,_,_,_] ? ;
Xs = [_,_,_,_,_,_,_] ? ;
Xs = [_,_,_,_,_,_,_] ? ;
...
如果a(Xs)
是包含偶数个元素的列表,则Xs
成功;如果b(Xs)
是包含奇数个参数的列表,则Xs
成功。a/1
成功。正如您所看到的,b/1
和a([]).
在每种情况下都会成功两次,除了even([]).
even([_|L]) :- odd(L).
odd([_]).
odd([_|L]) :- even(L).
只会成功一次。因此,它不是确定列表长度奇偶校验的有效谓词。
让我们用更具描述性的名称重写这些:
[]
现在让我们“读”他们所说的话:
[_|L]
是一个偶数列表L
是奇数列表,则[_]
是偶数列表
[_|L]
是一个奇怪的列表L
是偶数列表,even/1
是一个奇怪的列表这些听起来合乎逻辑,但为什么odd/1
和even([])
成功完成两次odd/1
除外?如果您查看[_]
的定义,odd([_]).
有两种方法可以成功。一个是通过odd/1
条款。第二个是第二个odd([_|[]]) :- even([]). % [_] == [_|[]]
,因为你有:
even/1
由于odd/1
和even([]).
调用(odd([_])
除外)最终会向下调用even([]).
even([_,_|L]) :- even(L).
odd([_]).
odd([_,_|L]) :- odd(L).
,因此您将获得两个解决方案。
将这些规则翻译成Prolog,包括以前的基本案例:
| ?- even(Xs).
Xs = [] ? ;
Xs = [_,_] ? ;
Xs = [_,_,_,_] ? ;
Xs = [_,_,_,_,_,_] ? ;
...
现在结果将是:
| ?- odd(Xs).
Xs = [_] ? ;
Xs = [_,_,_] ? ;
Xs = [_,_,_,_,_] ? ;
...
和
even --> [] | [_,_], even.
odd --> [_] | [_,_], odd.
根据CapelliC建议使用DCG,可以写出类似的规则:
| ?- phrase(even, L).
L = [] ? ;
L = [_,_] ? ;
L = [_,_,_,_] ? ;
...
结果:
| ?- phrase(odd, L).
L = [_] ? ;
L = [_,_,_] ? ;
L = [_,_,_,_,_] ? ;
...
和
odd([_]).
<小时/> 遵循@ false的建议,对原始代码进行更直接的“修复”将消除
even([]).
的冗余基本情况,因为它已经被even/1
的基本情况所涵盖。这也有点简单比上述解决方案更好,因为它利用了odd/1
和even/1
谓词之间的相互依赖关系(在上面的解决方案中,odd/1
和even([]).
even([_|L]) :- odd(L).
odd([_|L]) :- even(L).
独立存在)。
even --> [] | [_], odd.
odd --> [_], even.
或者,在DCG:
# ~/.tmuxinator/dyn.yml
name: dyn
root: ~/
windows:
# just using `echo` as a POC; this is where you'd make your function call
<%- `echo "111,222,333"`.split(',').each do |ip| %>
- tunnel-to-<%= ip.chomp %>: echo tunnel_to <%= ip %>
<%- end %>