如何在 Prolog 中回到 "repeat"?
How to go back to "repeat" in Prolog?
是否可以在不调用谓词且不创建新谓词的情况下返回到 Prolog 中的 repeat
?
我有以下代码
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.')
).
我得到的当前输出是
Welcome.
Print this message again? (yes/no)
yes.
You selected yes.
true.
节目结束。
我想要的输出是
Welcome.
Print this message again? (yes/no)
yes.
You selected yes.
Print this message again? (yes/no)
no.
计划结束。
我想避免的简单输出方式(我不想要这种输出。我不希望它多次显示 Welcome):
Welcome.
Print this message again? (yes/no)
yes.
Welcome.
You selected yes.
Print this message again? (yes/no)
no.
计划结束。
重复
repeat/0
是 simply defined as:
repeat.
repeat :- repeat.
或者,等价地:
repeat :- true ; repeat.
为了重复,您需要通过失败回溯到 repeat
调用,明确地使用 fail
或通过另一个失败谓词(参见上面的示例 link ).
...
repeat,
...,
fail.
一旦您想退出重复模式,您可以(并且应该)切断 !
决策树,这样您就没有悬空的 repeat
选择点。
如果你不这样做,解释器仍然有可能稍后回溯到 repeat
。
注意:!/0
的规则可以是 found here.
例子
具体来说,这意味着(顺便说一句,我使用 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
).
其他备注
请注意,OP 使用原子,而字符串就足够了。
实际上,原子(单引号)经过哈希处理,更适合用于符号推理,而字符串(双引号)未被保留,更适合显示消息。
本着同样的精神,在阅读时,我宁愿使用 read_string(end_of_line,_,S)
,它读取到行尾和 returns 一个字符串。使用 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
!.
删除 ->
可能会引起争议,因为其他人是如何争论要有更多病例的。这是基本原理:由于最初的问题似乎是关于 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).
为什么你不尝试做:
test :-
nl, write('Welcome.'),
nl, test_internal.
test_internal :-
write('Print this message again? (yes/no)'), nl,
read(Ans), nl,
( Ans == yes
-> write('You selected yes.'), nl, test_internal
; Ans == no, write('You selected no.'), !
; test_internal
).
编辑
如果您不能将谓词一分为二,另一种解决方案(使用 coredump 的)可能是:
test :-
nl, write('Welcome.'),
repeat, nl,
write('Print this message again? (yes/no)'), nl,
read(Ans), nl,
( Ans == yes
-> write('You selected yes.'), fail
; Ans == no, write('You selected no.'), !
; fail
).
编辑:使用 if-then 和不同布局的替代方法
为了进一步提高可读性,可以使用(->)/2
(if-then-ELSE-FAIL) (c.f. SWI-Prolog manual section on control predicates)。
此外,if-then-else 级联的不同布局也会有所帮助。
test :-
nl, write('Welcome.'),
repeat, nl,
write('Print this message again? (yes/no)'), nl,
read(Ans), nl,
( Ans == yes -> write('You selected yes.'), fail
; Ans == no -> write('You selected no.'), !
).
请注意,使用 if-then-ELSE-FAIL 并不是绝对必要的——可以使用连词。但是,使用它可以在将来轻松添加处理其他情况(maybe
、i_dont_know
、i_m_afraid
、i_gotta_go
)的代码。
是否可以在不调用谓词且不创建新谓词的情况下返回到 Prolog 中的 repeat
?
我有以下代码
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.')
).
我得到的当前输出是
Welcome.
Print this message again? (yes/no)
yes.
You selected yes.
true.
节目结束。
我想要的输出是
Welcome.
Print this message again? (yes/no)
yes.
You selected yes.
Print this message again? (yes/no)
no.
计划结束。
我想避免的简单输出方式(我不想要这种输出。我不希望它多次显示 Welcome):
Welcome.
Print this message again? (yes/no)
yes.
Welcome.
You selected yes.
Print this message again? (yes/no)
no.
计划结束。
重复
repeat/0
是 simply defined as:
repeat.
repeat :- repeat.
或者,等价地:
repeat :- true ; repeat.
为了重复,您需要通过失败回溯到 repeat
调用,明确地使用 fail
或通过另一个失败谓词(参见上面的示例 link ).
...
repeat,
...,
fail.
一旦您想退出重复模式,您可以(并且应该)切断 !
决策树,这样您就没有悬空的 repeat
选择点。
如果你不这样做,解释器仍然有可能稍后回溯到 repeat
。
注意:!/0
的规则可以是 found here.
例子
具体来说,这意味着(顺便说一句,我使用 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
).
其他备注
请注意,OP 使用原子,而字符串就足够了。 实际上,原子(单引号)经过哈希处理,更适合用于符号推理,而字符串(双引号)未被保留,更适合显示消息。
本着同样的精神,在阅读时,我宁愿使用 read_string(end_of_line,_,S)
,它读取到行尾和 returns 一个字符串。使用 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
!.
删除 ->
可能会引起争议,因为其他人是如何争论要有更多病例的。这是基本原理:由于最初的问题似乎是关于 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).
为什么你不尝试做:
test :-
nl, write('Welcome.'),
nl, test_internal.
test_internal :-
write('Print this message again? (yes/no)'), nl,
read(Ans), nl,
( Ans == yes
-> write('You selected yes.'), nl, test_internal
; Ans == no, write('You selected no.'), !
; test_internal
).
编辑
如果您不能将谓词一分为二,另一种解决方案(使用 coredump 的)可能是:
test :-
nl, write('Welcome.'),
repeat, nl,
write('Print this message again? (yes/no)'), nl,
read(Ans), nl,
( Ans == yes
-> write('You selected yes.'), fail
; Ans == no, write('You selected no.'), !
; fail
).
编辑:使用 if-then 和不同布局的替代方法
为了进一步提高可读性,可以使用(->)/2
(if-then-ELSE-FAIL) (c.f. SWI-Prolog manual section on control predicates)。
此外,if-then-else 级联的不同布局也会有所帮助。
test :-
nl, write('Welcome.'),
repeat, nl,
write('Print this message again? (yes/no)'), nl,
read(Ans), nl,
( Ans == yes -> write('You selected yes.'), fail
; Ans == no -> write('You selected no.'), !
).
请注意,使用 if-then-ELSE-FAIL 并不是绝对必要的——可以使用连词。但是,使用它可以在将来轻松添加处理其他情况(maybe
、i_dont_know
、i_m_afraid
、i_gotta_go
)的代码。