我目前正在学习Prolog,并且很难理解副作用。
我很乐于写一个谓词,它写一些N次字符串。给定的解决方案如下所示:
n_times(N) :- 1 =< N.
n_times(N) :- N > 1, N1 is N - 1, n_times(N1).
test_x(N) :- n_times(N), write('x'), fail.
test_x(_).
有人可以解释为什么这样做吗?为什么write('x')
被执行N次?据我了解,Prolog应该尝试为n_times(N)
找到解决方案,然后执行一次write('x')
。我想这与副作用有关,但是我找不到对此的实用解释。
我自己的解决方案如下:
test_x(N) :- write('x'), N1 is N - 1, N1 >= 1, test_x(N1).
在这里,我看到每次递归调用都被调用write
。
答案 0 :(得分:1)
这是所谓的故障驱动循环。
一种更容易达成协议的情况是
repeat :- true.
repeat :- repeat.
forever_x :- repeat, write('x'), fail.
永远在提示符下显示x
。
为什么?因为Prolog的目标连结(,
,“和”)就像嵌套循环:
find(G):- this(X1), that(X2).
就像(在 pseudocode 中)
def find(G):
foreach solution X1 to { this(X1) }:
foreach solution X2 to { that(X2) }:
yield G using the found values X1, X2.
回溯是自然发生的循环。 。如果对于某些X1
,没有X2
满足that(X2)
的情况,则没有{{ 1}}产生,并且外循环仅跳到满足G
的下一个X1
值。
Prolog对目标的析取(this(X1)
,“或”)只是循环的并置(只是将一个循环接一个循环)。
因此,;
的定义就像是由
repeat
和您的def repeat:
yield % yield an empty value that isn't used anywhere
repeat % call self, yielding again; and again; repeating endlessly
def forever_x:
foreach solution to { repeat }: % endless stream of empty solutions
foreach solution to { write('x') }: % there will be only one, empty solution
foreach solution to { fail }: % there will be no solutions, ever, so
yield % this will never happen
,就像
n_times/1
因此自然会成功,即“产量”, n 次。