Prolog是否有条件并重启系统,如Common Lisp?

mnd*_*rix 6 prolog iso-prolog

Common Lisp允许通过条件和重新启动进行异常处理.粗略地说,当函数抛出异常时,"捕手"可以决定"投掷者"应该如何进行.Prolog是否提供类似的系统?如果没有,是否可以在现有谓词的基础上构建一个步行和检查调用堆栈?

fal*_*lse 5

序言的ISO/IEC标准只提供了一个非常基本的异常和错误处理机制是-或多或少-这样的举动,Java提供,远离Common Lisp的丰富的机制,但仍存在一些值得注意的要点.特别是,除了实际的信令和处理机制之外,许多系统提供了类似的机制unwind-protect.也就是说,即使存在未处理的信号,也能确保执行目标的方法.

ISO throw/1,catch/3

提出/抛出异常throw(Term).首先Term创建一个副本,copy_term/2让我们调用它Termcopy然后这个新副本用于搜索catch(Goal, Pattern, Handler)其第二个参数统一的对应Termcopy.当Handler被执行时,所有unifications造成Goal被撤消.因此Handler,在throw/1执行时无法访问存在的替换.并且没有办法继续throw/1执行被执行的地方.

内部谓词的错误是由于执行信号发送throw(error(Error_term, Imp_def)),其中Error_term对应于一个ISO的错误类Imp_def可以提供实现定义额外的信息(如源文件,行数等).

在许多情况下,在本地处理错误会带来很大好处,但许多实现者认为它太复杂而无法实现.

使Prolog处理器在本地处理每个错误的额外工作是非常可观的,并且比Common Lisp或其他编程语言中的大得多.这是由于Prolog统一的本质.本地处理错误需要撤消在执行内置期间执行的统一:因此,实现者有两种可能性来实现:

  • 在调用内置谓词时创建一个"选择点",这会产生很多额外的开销,无论是创建这个选择点还是"尾随"后续绑定
  • 手动遍历每个内置谓词并根据具体情况决定如何处理错误 - 虽然这在运行时开销方面是最有效的,但这也是最昂贵且容易出错的方法

在内置函数中利用WAM寄存器会导致类似的复杂性.同样,可以在慢速系统或具有显着实现开销的系统之间进行选择.

exception_handler/3

然而,许多系统提供了内部更好的机制,但很少有系统为程序员提供这些机制.IF/Prolog提供exception_handler/3的参数与参数相同catch/3但在本地处理错误或异常:

[user] ?- catch((arg(a,f(1),_); Z=ok), error(type_error(_,_),_), fail).

no

[user] ?- exception_handler((arg(a,f(1),_); Z=ok), error(type_error(_,_),_), fail).

Z       = ok

yes

setup_call_cleanup/3

这个内置由很多系统提供.unwind-protect由于Prolog的回溯机制,它非常相似但需要一些额外的复杂性.查看其当前定义.


所有这些机制都需要由系统实现者提供,它们不能构建在ISO Prolog之上.