我需要遍历between/3
从 1 到Length
给Length
定列表长度的数字范围(例如使用 )。迭代的数字,比如说N
,然后应用于谓词,do_something
直到它停止失败。也就是说,do_something
搜索一个正确的N
,之后between/3
必须删除所有的选择点。但是,必须执行do_something
正确应用的所有选择点。N
拳头尝试是这样的:
% main(+InputList, -N, -OutputList)
main(InputList, N, OutputList) :-
length(InputList, Length),
between(1, Length, N),
% cut all between/3 choice points as soon as Num is instantiated
freeze(Num, !),
do_something(InputList, N, OutputList),
Num is N.
这不起作用,因为freeze/2
没有减少between/3
选择点。一个版本when/2
也不起作用。我收集,这是因为两者都在一个单独的线程中执行,freeze/2
并且when/2
不影响主线程所在between/3
的位置。
过了一会儿,我最终得到了以下代码,它可以满足需要,但效率低下:
main(InputList, N, OutputList) :-
length (InputList, Length),
between(1, Length, N),
do_something(InputList, N, _),
% cut all prior choice points as soon as proper N is found
!,
% start do_something over!
do_something(InputList, N, OutputList).
低效率是do_something
正确的选择点N
被执行了两次。首先是在切割之前,然后在切割之后再次。
虽然这个解决方案适用于我的情况,但它不适用于所有do_something
选择点必须只执行一次的一般情况。
请注意,N
必须是超出范围的最小值,1..Length
并且事先不知道。因此用do_something
.
有没有更好的解决方案?有没有办法实现类似于between/3
可以在以某种方式发出信号时停止的谓词?是否有一个专门的内置谓词可以满足需要?任何富有成效的想法都将受到高度赞赏。