Prolog:失败的语句执行两次
Prolog: failing statement executes twice
我是 Prolog 的初学者(使用 SWI-Prolog),我遇到以下问题:
我有一个规则定义如下:
start:-
write("Enter first list: "), read_list(List1),
write("Enter second list: "), read_list(List2),
equal_length(List1, List2),
compare(List1, List2, Alike),
write(" The lists are "), write(Alike).
start:- write("The lists should have the same length!!").
这是我阅读列表的方式:
read_list([H|T]):- read(H), H\=[], read_list(T).
read_list([]).
Compare 是一组将比较列表的规则,但它永远不会执行,我什至为此替换了它:
compare(_, _, "the same").
这是 equal_length 的样子:
equal_length([_|T1], [_|T2]):- equal_length(T1, T2).
equal_length([], []).
因此当列表的长度不同时它会失败。
问题是,当启动失败时,它再次执行第一次出现(List1 和 List2 已经绑定)!
我试过像这样更简单的东西:
hi:- 1>2, write("Nonsense").
hi:- write("Of course it doesn't work").
并且输出的是第二个字符串。
为什么第一个不那样做?
编辑:
经过进一步测试,我发现这种奇怪的行为只会在从该自定义方法读取列表时发生,并且只会在读取多个列表时发生。
你的代码的问题是缺乏对回溯的管理。当您的语句失败时,Prolog 将尝试为满足 equal_length
的列表获取新值。
这是一个使用 !
运算符处理回溯的示例:
start:-
read_list_data( List1, List2 ),
equal_length(List1, List2),
compare2(List1, List2, Alike),
write( List1 ), nl,
write(" The lists are "),
write(Alike).
start:- write("The lists should have the same length!!").
read_list([H|T]):- read(H),
H\=[],
read_list(T).
read_list([]).
compare2(_, _, 'the same').
equal_length([_|T1], [_|T2]):- equal_length(T1, T2).
equal_length([], []).
read_list_data( List1, List2 ) :-
write("Enter first list: "),
read_list(List1),
write("Enter second list: "),
read_list(List2),
!.
解释:
!
标记通过让 Prolog 知道它必须提交到目前为止所做的选择(即保留列表的值)来避免回溯不良行为。
我在这个 here 上找到了一个很好的信息来源,其中用树图解释了回溯。
我是 Prolog 的初学者(使用 SWI-Prolog),我遇到以下问题:
我有一个规则定义如下:
start:-
write("Enter first list: "), read_list(List1),
write("Enter second list: "), read_list(List2),
equal_length(List1, List2),
compare(List1, List2, Alike),
write(" The lists are "), write(Alike).
start:- write("The lists should have the same length!!").
这是我阅读列表的方式:
read_list([H|T]):- read(H), H\=[], read_list(T).
read_list([]).
Compare 是一组将比较列表的规则,但它永远不会执行,我什至为此替换了它:
compare(_, _, "the same").
这是 equal_length 的样子:
equal_length([_|T1], [_|T2]):- equal_length(T1, T2).
equal_length([], []).
因此当列表的长度不同时它会失败。 问题是,当启动失败时,它再次执行第一次出现(List1 和 List2 已经绑定)!
我试过像这样更简单的东西:
hi:- 1>2, write("Nonsense").
hi:- write("Of course it doesn't work").
并且输出的是第二个字符串。 为什么第一个不那样做?
编辑:
经过进一步测试,我发现这种奇怪的行为只会在从该自定义方法读取列表时发生,并且只会在读取多个列表时发生。
你的代码的问题是缺乏对回溯的管理。当您的语句失败时,Prolog 将尝试为满足 equal_length
的列表获取新值。
这是一个使用 !
运算符处理回溯的示例:
start:-
read_list_data( List1, List2 ),
equal_length(List1, List2),
compare2(List1, List2, Alike),
write( List1 ), nl,
write(" The lists are "),
write(Alike).
start:- write("The lists should have the same length!!").
read_list([H|T]):- read(H),
H\=[],
read_list(T).
read_list([]).
compare2(_, _, 'the same').
equal_length([_|T1], [_|T2]):- equal_length(T1, T2).
equal_length([], []).
read_list_data( List1, List2 ) :-
write("Enter first list: "),
read_list(List1),
write("Enter second list: "),
read_list(List2),
!.
解释:
!
标记通过让 Prolog 知道它必须提交到目前为止所做的选择(即保留列表的值)来避免回溯不良行为。
我在这个 here 上找到了一个很好的信息来源,其中用树图解释了回溯。