Reputation: 363
HI i have a simple knowledge database defined as:
carClass('X1','Oil','small').
carClass('X2','gas','big').
carClass('X3','Petrol','big').
carClass('X4','oil','small').
carClass('X5','Oil','small').
carClass('X6','gas','big').
I am trying to write a rule that will answer the query: Display all carClass that runs on 'oil' and IS NOT 'big'.
I am trying to implement it using:
OnOilButNotBig :-
carClass(CarClass,'oil',_),
carClass(CarClass,'oil', \+('big') ),
write(CarClass).
but this is not working.
Upvotes: 1
Views: 1014
Reputation: 477607
You have to understand the difference between a predicate and a functor.
If we oversimplify things a bit, a predicate is an identifier at the top level, so carClass/3
is a predicate, write/1
is a predicate and onOilButNotBig/0
is. You can call a predicate. A predicate with filled in arguments is a goal.
A functor on the other hand is an identifier not on the top level. Constants are functors, variables are functors, and functions with arguments are functors. Examples of functors are 'X1'
, 'oil'
and foo(X,bar,qux(2))
.
The negation expects a goal. 'big'
in this case is not a goal, in fact \+('big')
itself is a functor.
You can only solve this by turning the condition into a goal and ensure you will call it. This can be done like:
onOilButNotBig :-
carClass(CarClass,'oil',_),
carClass(CarClass,'oil',X),
\+(X = 'big'),
write(CarClass).
Furthermore I do not really see why you call carClass/3
twice. An equivalent and slightly more efficient program is the following:
onOilButNotBig :-
carClass(CarClass,'oil',X),
\+(X = 'big'),
write(CarClass).
Finally as @Repeat noted, you need to use names that start with a lowercase for predicates and functions.
Upvotes: 2
Reputation: 18726
First things first!
The code doesn't compile1. Why? Predicate names usually start with lowercase characters2.
My advice: instead of OnOilButNotBig
write onOilButNotBig
!
To express term inequality, use the right prolog-dif goal(s), like so:
onOilButNotBig :- dif(X, big), carClass(CarClass, oil, _), carClass(CarClass, oil, X), write(CarClass).
As a side remark, there are a few more issues with your code:
Use side-effect based I/O only when necessary.
In most cases, it is preferable to use the interactive prolog-toplevel for data input/output!
onOilButNotBig(CarClass) :- dif(X, big), carClass(CarClass, oil, _), carClass(CarClass, oil, X).
For the sake of readability, please do not use atoms like 'oil'
and 'Oil'
.
Pick one and stick to it! I suggest oil
(lowercase) which does not need escaping.
The goal carClass(CarClass, oil, _)
is completely redundant.
Why? It is a generalisation of the close-by goal carClass(CarClass,oil,X)
.
Footnote 1: When using b-prolog 8.1, sicstus-prolog 4.3.2, swi-prolog 7.3.14, and xsb 3.6.
Footnote 2: Names can also starting with uppercase characters if the right (escaping with single-quotes) is utilized.
Footnote 3: In general, redundant goals are ok, but they suggest to me your code will likely not behave as intended.
Upvotes: 1