3

我对在 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 ?-

谁能给我解释一下?它真的非常令人费解。我会很感激的。

4

3 回答 3

3

解析 Prolog 时,左括号是特殊的。如果标识符和左括号之间没有空格,则标识符始终被视为函子的名称(即使它不是字母数字)。括号内的任何内容都被视为此函子的参数列表。

但是,如果有空格,则括号将按其正常的分组表达式数学函数处理。这种表达式中的逗号起到布尔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
于 2012-10-18T15:04:40.330 回答
3

Prolog在运算符和括号之间需要一个空格(“分隔符”)。

如果没有空格,Prolog 解析器将其视为具有两个参数的函子。下面的两种情况与解析器没有什么不同。

mother(..., ...)
\+(..., ...)

但是,如果您放置一个空格,解析器会将其视为一个运算符和一个带括号的参数。有一个相反的规则(函子的名称和括号之间不能有空格),使得这一行也产生错误:

mother (..., ...)

经验法则是 - 如果是运算符,则在其后放置一个空格。

于 2012-10-17T23:53:25.740 回答
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==_

于 2012-10-18T06:03:32.137 回答