序言查询中的否定不起作用

Negation in prolog query is not working

嗨,我有一个简单的知识数据库定义为:

carClass('X1','Oil','small').
carClass('X2','gas','big').
carClass('X3','Petrol','big').
carClass('X4','oil','small').
carClass('X5','Oil','small').
carClass('X6','gas','big').

我正在尝试编写一个规则来回答查询:显示在 'oil' 上运行且不是 'big'.[= 的所有 carClass 12=]

我正在尝试使用以下方法实现它:

OnOilButNotBig :-
   carClass(CarClass,'oil',_),
   carClass(CarClass,'oil', \+('big') ),
   write(CarClass).

但这不起作用。

你必须理解 predicatefunctor.

之间的区别

如果我们把事情简单化一点,谓词是一个标识符在顶层,所以carClass/3是一个谓词,write/1是一个谓词onOilButNotBig/0 是。您可以调用谓词。填充参数的谓词是 目标.

另一方面,仿函数是不在顶层的标识符。 常量 是函子,变量 是函子,带参数的函数 是函子。函子的例子有 'X1''oil'foo(X,bar,qux(2)).

否定期望 目标'big' 在这种情况下不是目标,实际上 \+('big') 本身就是一个函子。

你只能通过将条件 变成目标 并确保你会调用它来解决这个问题。这可以像这样完成:

onOilButNotBig :-
   carClass(CarClass,'oil',_),
   carClass(CarClass,'oil',X),
   \+(X = 'big'),
   write(CarClass).

此外,我真的不明白你为什么两次调用 carClass/3。一个等效且稍微更有效的程序如下:

onOilButNotBig :-
   carClass(CarClass,'oil',X),
   \+(X = 'big'),
   write(CarClass).

最后,如 所述,您需要为谓词和函数使用以小写字母开头的名称。

要事第一!

  • 代码无法编译1。 为什么?谓词名称通常以小写字母开头2.

    我的建议:将 <b>On</b>OilButNotBig 写成 <b>on</b>OilButNotBig !

  • 要表达术语不平等,请使用正确的 目标,如下所示:

    onOilButNotBig :-
       dif(X, big),
       carClass(CarClass, oil, _),
       carClass(CarClass, oil, X),
       write(CarClass).
    
  • 附带说明一下,您的代码还有一些问题:

    1. 仅在必要时使用基于side-effect的I/O。

      在大多数情况下,最好对数据使用交互式 input/output!

      onOilButNotBig(CarClass) :-
         dif(X, big),
         carClass(CarClass, oil, _),
         carClass(CarClass, oil, X).
      
    2. 为了可读性,请不要使用像'oil''Oil'这样的原子。

      选择一个并坚持下去!我建议不需要转义的oil(小写)。

    3. 目标 carClass(CarClass, oil, _) 完全 多余。

      为什么?它是 close-by 目标 carClass(CarClass,oil,<b>X</b>).

      [=75= 的概括]

脚注 1: 使用时 8.1, 4.3.2, 7.3.14, and 3.6。
脚注 2: 名称 可以 如果使用右(使用 single-quotes 转义)也可以以大写字符开头。
脚注 3: 一般来说,冗余目标是可以的,但它们向我暗示您的代码可能不会按预期运行。