I want to know what @<
means in Prolog?
I encountered this symbol in this line of code while reading about the Bridge and Torch Problem:
select_one_or_two(L, [Sel1,Sel2], L2) :-
select(Sel1, L, NewL),
select(Sel2, NewL, L2),
Sel1 @< Sel2.
The comparative operators that start with @
are more general than the ones that don't. With operators such as </2
, you can only compare numeric values and expressions (involving literal numerics and variables that are instantiated with numeric values). So, with </2
you can do this:
?- X = 2, Y = 3, X + Y < 2*Y.
X = 2,
Y = 3.
?- X = 2, Y = 3, X + Y > 2*Y.
false.
?-
But you will get an error in the following cases if the expressions don't evaluate to a known numeric:
?- Y = 3, X + Y < 2*Y.
ERROR: </2: Arguments are not sufficiently instantiated
Or:
?- a < b.
ERROR: </2: Arithmetic: `a/0' is not a function
However, using @</2
you can compare lots of different types of objects in prolog. The comparison evaluation follows the rules described in the link that @Ankur gave. To understand these rules, you'll need to know what Prolog terminology means, such as term
, functor
, atom
, etc (see, for example, Prolog Terms)
Looking at some examples:
?- a @< b.
true.
?- a(1) @< a(2).
true.
?- b(1) @< a(2).
false.
?- 20 @< a.
true.
These are pretty straight-forward, following the rules. Here's a more interesting case (from above):
?- Y = 3, X + Y @< 2*Y.
false.
Why would X + Y
be considered "not less than" 2*Y
? Prolog would internally look at this as:
`+(X,3) @< *(2,3).`
(Note Y
is instantiated to 3
.) These are compound terms (they aren't individual atoms or variables). If we look through the comparison rules, the matching rule is:
Compound terms are first checked on their arity, then on their functor name (alphabetically) and finally recursively on their arguments, leftmost argument first.
The arity of both terms is 2. The functor names are +
and *
respectively. Those are different. And in teh ASCII collating sequence, +
comes after *
. Therefore it is not true that +
"is less than" *
, and therefore not true that +(X,3) @< *(2,3).
Thus, it is not true that Y = 3, X + Y @< 2 * Y.
Note also that @</2
doesn't evaluate numeric expressions. So even with X
and Y
instantiated as values, you will get:
?- X = 2, Y = 3, X + Y @< 2*Y.
false.
Whereas, when we had </2
here, this is true, since the expression X + Y < 2*Y
, when evaluated, is true. When variables are simply unified, it understands that, however, so you would have:
| ?- X @< Y.
yes
But on the other hand:
| ?- X = 2, Y = 1, X @< Y.
no
In this case X @< Y
is seen as 2 @< 1
due to the unification of X
with 2
and Y
with 1
and the numeric rule kicks in.
Having said all that, the use of @</2
in the predicate select_one_or_two
enables that predicate to be usable on lists of all sorts of objects, not just numbers or fully instantiated numeric expressions. If it had used </2
, then the following would work:
?- select_one_or_two([2,1,3], X, Y).
X = [2, 3],
Y = [1] ;
X = [1, 2],
Y = [3] ;
X = [1, 3],
Y = [2] ;
false.
But the following fails:
?- select_one_or_two([b,a,c], X, Y).
ERROR: </2: Arithmetic: `b/0' is not a function
?-
However, with the @<
operator, it works:
?- select_one_or_two([b,a,c], X, Y).
X = [b, c],
Y = [a] ;
X = [a, b],
Y = [c] ;
X = [a, c],
Y = [b] ;
false.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With