我在SWI Prolog中使用否定有一个奇怪的问题。当我在否定“\ +”之后使用以下代码而没有空格时,它会给出错误:
2 ?- assert((only_child(X) :- mother(M,X),\+(mother(M,_),\+ X==_))).
true.
3 ?- only_child(cathy).
ERROR: only_child/1: Undefined procedure: (\+)/2
ERROR: However, there are definitions for:
ERROR: (\+)/1
Exception: (7) \+(mother(melody, _G2102), \+cathy==_G2107) ? creep
4 ?-
但是,如果我在否定后使用空格,那么它的效果非常好。
2 ?- assert((only_child(X) :- mother(M,X),\+ (mother(M,_),\+ X==_))).
true.
3 ?- only_child(cathy).
false.
4 ?-
但是以下代码适用于两者,使用“\ +”之后的空格而不使用空格。
4 ?- \+ father(michael,cathy).
false.
5 ?- \+father(michael,cathy).
false.
6 ?-
有人可以向我解释一下吗?它真的很令人费解。我会非常感激。
答案 0 :(得分:3)
Prolog requires操作符和括号之间的空格(“分隔符”)。
如果没有空格,Prolog解析器会将其视为具有两个参数的仿函数。以下两种情况与解析器没有区别。
mother(..., ...)
\+(..., ...)
但是,如果放置一个空格,解析器会将其视为运算符和括号的参数。有一个相反的规则(仿函数的名称和括号之间必须没有空格),使这一行也产生错误:
mother (..., ...)
经验法则是 - 如果是操作员,请在其后面留一个空格。
答案 1 :(得分:3)
解析Prolog时,左括号是特殊的。如果标识符和开始paren之间没有空格,则标识符始终被视为仿函数的名称(即使它不是字母数字)。无论是什么内部的parens被视为这个仿函数的参数列表。
但是,如果有空格,则按照分组表达式的正常数学函数处理paren。这样的表达式中的逗号用作布尔and
运算符的角色。
所以:
"func(A,B)" - OK - invoke `func` on parameters `A`, `B`
"func (A,B)" - syntax error - interpreted as an identifier stuck together
with an AND expression
"\+ (A,B)" - OK - operator `\+` acting on `(A,B)` (A and B)
"\+(A,B)" - error - invoke `\+` with two parameters `A`, `B`
but \+ only takes one argument
"\+(A)" - OK - since `\+` takes one argument, it can
be invoked as a functor with one argument inside parens
解析器也足够聪明,可以从标识符中拆分运算符(第一个字母触发新标记):
"\+ father(A,B)" - OK - invoke functor `father` with `A` and `B`,
negate the result
"\+father(A,B)" - still OK - the parser will stop reading the
name of the operator when it encounters the 'f',
so the result is same as above
答案 2 :(得分:2)
我认为解释应该是Prolog不允许在仿函数和参数之间留出空格。
运算符是具有适当声明的仿函数(请参阅op / 3和current_op / 3)。在声明之后我们可以选择如果要将仿函数作为运算符使用。一个人为的例子,算术:
?- X is +(1,*(5,8)).
X = 41.
?- X is 1+5*8.
X = 41.
?- X is 1+(5*8).
X = 41.
然后您看到的错误类似于此
?- X is + (1,*(5,8)).
ERROR: evaluable `1,5*8' does not exist
Exception: (6) expand_goal(_G209 is + (1, 5*8), _G292, user, [user, system], _G295) ? creep
即。要用作仿函数的原子+
在括号之前不允许空格。
修改强>
值得注意的另一件事是,
被声明为运算符,意思是AND
,但是也是一个词法元素,用作参数分隔符。然后在第二种情况下,+将应用于联合mother(M,_) AND \+ X==_