Question

For languages such as Java and C which allow syntactic sugar with operators, i.e. infix, they use precedence and associativity.

Prolog also uses associativity:
left-associative - yfx
right-associative - xfy

but why is there xfx?

The only thing I have found on the internet giving any more clarity is

xfx means that the operator 'dominates' upon its branches, while xfy or yfx stand for 'list construction', in sense that allow chaining expressions of same priority.

from: Interpretation of Prolog's operator in an exercise by CapelliC

If the answer can include examples where xfx is needed because xfy and yfx fail/don't have meaning, that would be appreciated.

For Prolog reference: The Prolog Built-in Directive op

As false notes:

Please note that the operators you give in above link differ from both the standard and SWI! They are outdated by at least 10 years. As an example, it should be current_op(200,fy,-).

After reading the two current answers by CapelliC and false it became clear that non-associative was the key word to locating more relevant information. So Operator associativity now make more sense with regards to xfx when paying attention to non-associative section.

Was it helpful?

Solution

The specifier of an operator denotes the class (prefix, infix, postfix) and associativity of an operator.

xfx means that the operator does not permit any form of associativity. In other words: it does not nest with operators of the same priority. However, it does still nest with operators of a lower priority.

The largest part of such operators are predicates of arity two that are used for comparison-like meaning and where nesting would have - at least - an entirely different meaning than what the predicate is about. They are all located at priority 700: High enough to allow all arithmetic operators to work without bracketing ; low enough to work with control constructs and related meta-predicates that expect goals as arguments. Think of (\+)/1, (;)/2, (',')/2.

Consider =<: If you want to state that X is between 1 and 3 you cannot write 1 =< X =< 3 because neither (1 =< X) =< 3 nor 1 =< (X =< 3) make sense in Prolog. In fact, both would lead to an evaluation error. You have to write 1 =< X, X =< 3. which means =<(1, X), =<(X, 3).

For some cases it might make sense to nest, think of (A = B) = P. Here, the first = is just a functor like any other of arity 2, while the second = is the built-in predicate (=)/2 for equality/unification. But such cases are rare and it is worth highlighting them with an extra pair of round brackets.

Note also that :- :- a. is invalid syntax, because (:-)/1 again does not nest.

Arithmetic operators are typically left associative since you process them left-to-right like 1+2+4, first computing 1+2 and only then adding 4. The notable exception is (^)/2: This is so, because (X^Y)^Z =:= X^(Y*Z) whereas (X^(Y^Z)) denotes a term that cannot be expressed with simpler operators.

OTHER TIPS

For instance, (:-)/2 it's clearly an operator that can used only once, because it separates the head from the body.

The separation is 'relative', you could have in a rule, for instance

my_rule :- assertz((a :- b, c)).

Here is the full list of (default) xfx operators from SWI-Prolog

?- setof((X,Y), current_op(X,xfx,Y), L), maplist(writeln, L).
200, (**)
700, (<)
700, (=)
700, (=..)
700, (=:=)
700, (=<)
700, (==)
700, (=@=)
700, (=\=)
700, (>)
700, (>=)
700, (@<)
700, (@=<)
700, (@>)
700, (@>=)
700, (\=)
700, (\==)
700, (\=@=)
700, (as)
700, (is)
1200, (-->)
1200, (:-)

I don't think the current status of the prolog standard op scene is necessarily a definitive guide to how to use op. Reduction of each op to these type codes (xf, fx, yfx, etc.) was a brilliant invention, but such an invention is more a product of the zeitgeist than the product of any particular rationale (.i.e. the outcome is not necessarily defined by the intentions of the inventor).

xfy is an op that has a source on the left and a target on the right. xfx is an op that has a source on the left and a source on the right. yfx is an op that has a target on the left and a source on the right.

'xfy' is (generally) associated with :

  • left-to-right
  • top-to-bottom
  • domination
  • being first
  • being declarativ
  • being ignorant of the 'yfx'

'xfx' is (generally) associated with:

  • judgement of the operands
  • comparison of things of equal class
  • that's all I have for this weirdo

'yfx' is (generally) associated with:

  • right-to-left
  • bottom-to-top
  • egalitarian
  • being last (thus ultimately achieving true domination)
  • being procedural
  • being tolerant of the shenanigans of the 'xfy'

Note that the following works out because the 'x' and 'y' are partnered throughout :

  xfy xfx yfx

but in contrast this does not work out:

  yfx xfx xfy

Some examples (untested, just sketches)...

  (term_expansion((_a),(true)):-(asserta(_a))) .
  (term_expansion((_a | _b),(_b)):-(expand_term(_a,_c),asserta(_c))) .

  :-
  (op(10'1200,'xfy',':='))
  ,
  (op(10'1200,'xfx',':~'))
  ,
  (op(10'1200,'yfx',':-'))
  .

  (term_expansion((_a := _b :- _c),(term_expansion(_a,_b):-_c))) .
  (term_expansion((_a :~ _b :- _c),(goal_expansion(_a,_b):-_c))) .
  (term_expansion((_a := _b1 :~ _b2 :- _c),((_a := _b1 :- _c) | (_a :~ _b2 :- _c)))) .

In that example the :- is yfx. The syntax is ___consequent___ :- ___precedent___ ; the right is the source aka the domain (thus evaluated first), the left is the target aka the codomain (thus evaluated second).

In that example the :~ is xfx. The syntax is ___goal_1___ :~ ___goal_2__. It corresponds to a goal_expansion.

In that example the := is xfy. The syntax is ___precedent___ := ___consequence__. It corresponds to a term_expansion.

  :-
  (op(10'700,'xfy','@='))
  ,
  (op(10'700,'xfx','\\='))
  ,
  (op(10'700,'yfx','#='))
  .

  (_x @= _y) :- ('='(_x,_y)) . % .i.e. term equality
  % (_x1 \= _x2)   % prolog builtin, not equal
  % (_y #= _x)   % via clpfd, math is generally simplification/\answer is left

The \= is, in my opinion, the definitiv example of an xfx operator.

The terminology source | domain, target | codomain, is from here : https://en.wikipedia.org/wiki/Morphism#Definition.

I don't know much about category theory (yet), but I do wonder if the xfx has something to do with the identity morphism.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top