如何在Prolog中重新"重复"?

Lor*_*uel 5 prolog repeat

是否有可能在不调用函数(谓词)且不创建新函数的情况下返回Prolog中重复?

我有以下代码

test :- nl,
write('Welcome.'),nl,
repeat, write('Print this message again? (yes/no)'),nl,
read(Ans),nl,
(
    Ans == yes -> write('You selected yes.'), nl
;
    write('You selected no.')
).
Run Code Online (Sandbox Code Playgroud)

我得到的当前输出是

Welcome.
Print this message again? (yes/no)
yes.
You selected yes.
true.
Run Code Online (Sandbox Code Playgroud)

程序结束.

我想要的输出是

Welcome.
Print this message again? (yes/no)
yes.
You selected yes.
Print this message again? (yes/no)
no.
Run Code Online (Sandbox Code Playgroud)

计划结束.

我想避免的简单输出方式(我不想要这个输出.我不希望它显示欢迎多次):

Welcome.
Print this message again? (yes/no)
yes.

Welcome.
You selected yes.
Print this message again? (yes/no)
no.
Run Code Online (Sandbox Code Playgroud)

计划结束.

cor*_*ump 7

重复

repeat/0简单地定义为:

repeat.
repeat :- repeat.
Run Code Online (Sandbox Code Playgroud)

或者,等效地:

repeat :- true ; repeat.
Run Code Online (Sandbox Code Playgroud)

为了重复,您需要repeat通过失败来回溯到调用,fail或者通过另一个失败的谓词明确地回溯(参见上面链接中的示例).

...
repeat,
...,
fail.
Run Code Online (Sandbox Code Playgroud)

一旦你想退出重复模式,你可以(并且应该)剪切!决策树,这样你就没有悬空repeat选择点.如果不这样做,翻译仍然可以回溯到repeat以后.

注意:这里的规则!/0可以在这里找到.

特别是你的例子,这意味着(顺便说一下,我用writeln):

test :- 
  nl,
  writeln('Welcome.'),
  repeat, 
  writeln('Print this message again? (yes/no)'),
  read(Ans),nl,
  (Ans == yes -> 
    writeln('You selected yes.'), 
    fail % backtrack to repeat
  ; writeln('You selected no.'),
    ! % cut, we won't backtrack to repeat anymore
  ).
Run Code Online (Sandbox Code Playgroud)

其他言论

请注意,OP使用原子,而字符串就足够了.实际上,原子(单引号)被散列并且优先用于符号推理,而字符串(双引号)没有被实现并且更适合于显示消息.

本着同样的精神,在阅读时,我宁愿使用 read_string(end_of_line,_,S),它会读到行尾并返回一个字符串.有了read/1,我不得不关闭输入流Ctrl+D,这很烦人.

此外,我们可以->完全摆脱:

test :- 
  nl,
  writeln("Welcome."),
  repeat, 
  writeln("Print this message again? (yes/no)"),
  read_string(end_of_line,_,Ans),
  nl,
  write("You selected "),
  write(Ans),
  writeln("."),
  Ans == "no", % Otherwise, repeat
  !.
Run Code Online (Sandbox Code Playgroud)

如果->其他人争论有更多案件,那么删除可能会引起争议.这是什么道理:因为原来的问题似乎是关于家庭作业repeat,有关处理的部分yes,no和坏的输入明确地似乎尚未得以确认,并坦率地说,没有真正意义.我保留了原始语义并合并了yes输入和输入错误的情况:毕竟,用户说什么时会发生什么yes?我们重复,就像用户键入意外输入时一样.我们不这样做的唯一情况repeat是什么时候Ans == no.

现在,如果我们想要更改原始代码的行为以便明确检查所有可能类型的输入,这是一个尝试:

test :- 
  nl,
  writeln("Welcome."),
  repeat, 
  writeln("Print this message again? (yes/no)"),
  read_string(end_of_line,_,Ans),
  nl,
  (memberchk(Ans,["yes","no"]) ->
    write("You selected "),
    write(Ans),
    writeln("."),
    Ans == "no",
    !
  ; writeln("Bad input" : Ans),
    fail).
Run Code Online (Sandbox Code Playgroud)