确保谓词确定性地成功
Ensuring that a predicate succeeds deterministically
几乎相同,但不完全相同。相反,我如何要求目标确定性地(恰好一次)成功并且不留下任何选择点?
这在用作命令行工具的 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,但找不到明显描述这种情况的错误。
抛出错误确实更好,还是直接失败?如果抛出错误是首选,那么错误是什么?
编辑:我不确定该怎么做,因为特别是当涉及到副作用时,比如向标准输出写东西,让副作用发生感觉很不对 然后失败。抛出异常几乎是必要的。这也可以决定剩余的选择点是无害的(如果不需要的话)并且只捕获异常,然后写入标准错误或 return 不同的退出代码。
但我真的不知道如何正确描述异常,所以我不知道该抛出什么术语。
查看 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
是 预期 ,这反映在抛出的错误术语中。
这在用作命令行工具的 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,但找不到明显描述这种情况的错误。
抛出错误确实更好,还是直接失败?如果抛出错误是首选,那么错误是什么?
编辑:我不确定该怎么做,因为特别是当涉及到副作用时,比如向标准输出写东西,让副作用发生感觉很不对 然后失败。抛出异常几乎是必要的。这也可以决定剩余的选择点是无害的(如果不需要的话)并且只捕获异常,然后写入标准错误或 return 不同的退出代码。
但我真的不知道如何正确描述异常,所以我不知道该抛出什么术语。
查看 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
是 预期 ,这反映在抛出的错误术语中。