This other question几乎一样,但不完全相同。相反,我如何要求确定性地(确切地一次)成功并且不留下任何选择点?
这在用作命令行工具的Prolog程序的上下文中特别有用:可能从标准输入读取,接受参数并写入标准输出。在这样的程序中,在完成工作后留下一个选择点总是程序员的错误。
SWI-Prolog提供deterministic/1
,所以可以写一下:
( deterministic(true)
-> true
; fail
)
建议采用另一种更便携的方法:
is_det(Goal, IsDet) :-
setup_call_cleanup(true, Goal, Det=true),
( Det == true
-> IsDet = true
; !,
IsDet = false
).
然而,在发生这种情况时抛出错误似乎很有用,但我不知道这个错误是什么。我仔细查看了ISO error terms并且找不到明显描述这种情况的错误。
抛出错误确实更好,还是我应该失败?如果首选抛出错误,该错误会是什么?
编辑:我不知道该怎么做,因为特别是当涉及副作用时,比如写一些标准输出,发生副作用感觉非常错误然后他们失败了。几乎有必要抛出异常。这使得还可以确定剩余的选择点是无害的(如果不是可取的)并且只捕获异常,然后写入标准错误或返回不同的退出代码。
但是我真的不知道什么是正确描述了异常,所以我不知道要抛出什么术语。
答案 0 :(得分:3)
按照Ulrich Neumerkel在SWI-Prolog邮件列表上的建议查看call_semidet/1
:
call_semidet/1
- clean removal of choice-points
在其中,他建议:
call_semidet(Goal) :- ( call_nth(Goal, 2) -> throw(error(mode_error(semidet,Goal),_)) ; once(Goal) ).
这个提议的mode_error
是一个非常好的开始。
在精神上,它遵循其他错误:在这种情况下,模式semidet
预期,这反映在抛出的错误术语中。