Prolog 无法使用is/2谓词将变量N增加1

Prolog 无法使用is/2谓词将变量N增加1,prolog,Prolog,无法使用is/2谓词将变量N递增1N在重复循环中始终为0。为什么?如何增加它 :- dynamic audible/1, flashes/1,tuned/1. audible(false). flashes(false). tuned(false). turn :- N is 0 , repeat , ( incr(N,N1) , N1 =:= 5000 , audible(true) , flashes(true) -> retr

无法使用
is/2
谓词将变量
N
递增1<代码>N在重复循环中始终为0。为什么?如何增加它

:- dynamic audible/1, flashes/1,tuned/1.

audible(false).
flashes(false).
tuned(false).

turn :-
  N is 0 ,
  repeat ,
  (
    incr(N,N1)    ,
    N1 =:= 5000   ,
    audible(true) ,
    flashes(true) -> retractall(tuned) ,
    retractall(flashes) ,
    retractall(audible) ,
    assert( tuned(true)   ) ,
    assert( flashes(true) ) ,
    assert( audible(true) )
  ) .

incr(X,X1) :- X1 is X+1 .

因为
N是0
。Prolog中的变量不是。以下是跟踪循环时发生的情况:

?- trace, turn.
Call: (7) turn ? 
Call: (8) _G492 is 0 ? 
Exit: (8) 0 is 0 ? 
Call: (8) repeat ? 
Exit: (8) repeat ? 
Call: (8) incr(0, _G493) ? 
Call: (9) _G495 is 0+1 ? 
Exit: (9) 1 is 0+1 ? 
Exit: (8) incr(0, 1) ? 
Call: (8) 1=:=5000 ? 
Fail: (8) 1=:=5000 ? 
Redo: (8) repeat ? 
Exit: (8) repeat ? 
Call: (8) incr(0, _G493) ? 
Call: (9) _G495 is 0+1 ? 
Exit: (9) 1 is 0+1 ? 
Exit: (8) incr(0, 1) ? 
Call: (8) 1=:=5000 ? 
Fail: (8) 1=:=5000 ? 
Redo: (8) repeat ? 
Exit: (8) repeat ? 
Call: (8) incr(0, _G493) ? 
Call: (9) _G495 is 0+1 ? 
Exit: (9) 1 is 0+1 ? 
Exit: (8) incr(0, 1) ? 
Call: (8) 1=:=5000 ? 
Fail: (8) 1=:=5000 ? 
Redo: (8) repeat ? 
看看那里发生了什么?您反复询问1是否为5000,但失败,然后重试。但是N和N1的值在谓词体中永远不会改变。Prolog没有您习惯的块作用域变量。您需要将循环体变成一个单独的谓词,并使用递归来完成您要做的事情。它看起来像这样:

turn :- loop(0).
loop(5000) :-
  audible(true), ...
loop(N) :-
  incr(N, N1),
  loop(N1).

顺便说一下,已经有一个谓词
succ/2
,它执行您试图使用
incr/2

执行的操作,因为
N是0
。Prolog中的变量不是。以下是跟踪循环时发生的情况:

?- trace, turn.
Call: (7) turn ? 
Call: (8) _G492 is 0 ? 
Exit: (8) 0 is 0 ? 
Call: (8) repeat ? 
Exit: (8) repeat ? 
Call: (8) incr(0, _G493) ? 
Call: (9) _G495 is 0+1 ? 
Exit: (9) 1 is 0+1 ? 
Exit: (8) incr(0, 1) ? 
Call: (8) 1=:=5000 ? 
Fail: (8) 1=:=5000 ? 
Redo: (8) repeat ? 
Exit: (8) repeat ? 
Call: (8) incr(0, _G493) ? 
Call: (9) _G495 is 0+1 ? 
Exit: (9) 1 is 0+1 ? 
Exit: (8) incr(0, 1) ? 
Call: (8) 1=:=5000 ? 
Fail: (8) 1=:=5000 ? 
Redo: (8) repeat ? 
Exit: (8) repeat ? 
Call: (8) incr(0, _G493) ? 
Call: (9) _G495 is 0+1 ? 
Exit: (9) 1 is 0+1 ? 
Exit: (8) incr(0, 1) ? 
Call: (8) 1=:=5000 ? 
Fail: (8) 1=:=5000 ? 
Redo: (8) repeat ? 
看看那里发生了什么?您反复询问1是否为5000,但失败,然后重试。但是N和N1的值在谓词体中永远不会改变。Prolog没有您习惯的块作用域变量。您需要将循环体变成一个单独的谓词,并使用递归来完成您要做的事情。它看起来像这样:

turn :- loop(0).
loop(5000) :-
  audible(true), ...
loop(N) :-
  incr(N, N1),
  loop(N1).

顺便说一下,这里已经有一个谓词
succ/2
,它完成了您试图使用
incr/2

来完成的操作,我不知道您在这里试图完成什么,但似乎您正在尝试编写过程性的prolog代码

它不起作用

Prolog变量只写一次:与对象统一后,它们不再是变量。他们成为了那个目标,直到那个统一通过回溯被撤销

你需要学会递归思考,并使用递归循环来做你想做的事情

轮到你了/0谓词

turn :-
  N is 0 ,
  repeat ,
  (
    incr(N,N1)    ,
    N1 =:= 5000   ,
    audible(true) ,
    flashes(true) -> retractall(tuned) ,
    retractall(flashes) ,
    retractall(audible) ,
    assert( tuned(true)   ) ,
    assert( flashes(true) ) ,
    assert( audible(true) )
  ) .
执行以下操作。它:

  • 将N与0统一
  • 用N+1增加N1,使N1=1
  • 如果N1不是5000(实际值),则失败
  • 失败时,prolog引擎开始回溯
  • 通过incr/2进行回溯将撤消N1的绑定,使其再次变为变量
  • 回溯到repeat/0,再次成功
此时,您回到了开始的位置,N绑定到0


清洗、冲洗、重复。

我不知道您在这里试图完成什么,但似乎您正在尝试编写过程性的prolog代码

它不起作用

Prolog变量只写一次:与对象统一后,它们不再是变量。他们成为了那个目标,直到那个统一通过回溯被撤销

你需要学会递归思考,并使用递归循环来做你想做的事情

轮到你了/0谓词

turn :-
  N is 0 ,
  repeat ,
  (
    incr(N,N1)    ,
    N1 =:= 5000   ,
    audible(true) ,
    flashes(true) -> retractall(tuned) ,
    retractall(flashes) ,
    retractall(audible) ,
    assert( tuned(true)   ) ,
    assert( flashes(true) ) ,
    assert( audible(true) )
  ) .
执行以下操作。它:

  • 将N与0统一
  • 用N+1增加N1,使N1=1
  • 如果N1不是5000(实际值),则失败
  • 失败时,prolog引擎开始回溯
  • 通过incr/2进行回溯将撤消N1的绑定,使其再次变为变量
  • 回溯到repeat/0,再次成功
此时,您回到了开始的位置,N绑定到0

清洗,漂洗,重复