我已经定义了一个运算符#
:
:- op(500, yfx, #).
我已经写了以下规则来检查术语是否格式正确:
valid(X):- integer(X).
valid(X # Y):- valid(X), valid(Y).
我想编写一个谓词check/1
,如果它的参数有效则返回true,否则返回false。我写了这个:
check(Exp):- catch(valid(Exp), error(syntax_error(_),_), fail), !.
当Exp格式正确时,它返回true。但是,当它不合法时,它不会捕获语法错误:
?- check(5 ## 6).
ERROR: [Thread pdt_console_client_0_Default Process] Syntax error: Operator expected
ERROR: [Thread pdt_console_client_0_Default Process] check(5
ERROR: [Thread pdt_console_client_0_Default Process] ** here **
ERROR: [Thread pdt_console_client_0_Default Process] ## 6) .
我正在使用SWI-Prolog version 7.4.1 for amd64
。
如果出现错误,如何捕获语法错误并使check
返回false?
答案 0 :(得分:3)
在您的情况下,问题是如果首先输入有效的Prolog目标,则check/1
仅被称为。
因此,当check/1
已被调用时,语法肯定至少是一个有效的Prolog术语,即使它从check/1
本身的角度来看也没有意义。如果语法不有效,则Prolog toplevel 已经引发错误,甚至没有调用check/1
。
因此,要更好地控制语法问题,您需要自己阅读这些条款。
有几种方法可以做到这一点。一个简单的方法是使用read/1
。例如:
?- catch(read(X), Error, true). |: check(5##6). Error = error(syntax_error(operator_expected), stream(user_input, 8, 7, 347)).
通过这种方式,您基本上可以构建自己的顶层,从而可以更好地控制此类问题。另请参阅read_term/2
以及一些有助于此的相关谓词。
与此类问题相关的一个重要选项是variable_names/1
:它产生Prolog变量与其原子名称之间的对应关系,以便您可以报告可读绑定。这是最重要的部分,ISO标准化的最新进展极大地促进了这些功能。也许,在适当的时候,我们将能够在Prolog中编写可移植的toplevels,可用于多个系统。有许多应用程序可以从中受益,你的其中之一就是其中之一。