Operators: OP & PRIO

Monadic operators (-, +, NOT, ABS, ENTIER, ROUND, ODD, SIGN, REPR, LENG, SHORTEN, UPB, LWB, RE, IM, CONJ, BIN, ...) bind tighter than any dyadic operator.

32.1 Standard dyadic priorities

+* I (complex construction) ** UP DOWN SHL SHR LWB UPB (dyadic forms)

* / % (OVER) %* (MOD) ELEM < <= >= > (LT LE GE GT) = /= (EQ NE)

+:= -:= *:= /:= %:= %*:= +=: (PLUSAB MINUSAB TIMESAB DIVAB OVERAB MODAB PLUSTO)

Monadic operators (-, +, NOT, ABS, ENTIER, ROUND, ODD, SIGN, REPR, LENG, SHORTEN, UPB, LWB, RE, IM, CONJ, BIN, ...) bind tighter than any dyadic operator. Hence -x 2 means (-x) 2 — a classic surprise.

32.2 Declaring operators

Operator names can be bold words (BIGGER) or symbol sequences (+, <>, +*). Monadic and dyadic forms are distinguished by the number of operands.

BEGIN
   PRIO BIGGER = 6;                          # priority for a new dyadic operator #
   OP BIGGER = (INT a, b) INT: (a > b | a | b);
   OP DOUBLE = (INT a) INT: 2 * a;           # monadic: no PRIO needed #
   print((3 BIGGER 8, DOUBLE 21, newline))
END

32.3 Overloading

Operators are overloaded on operand modes:

Rule: two declarations of the same operator in the same range must not have operand modes that are "firmly related" (one coercible to the other in a firm context), or a call could be ambiguous.

BEGIN
   MODE VEC = STRUCT (REAL x, y, z);
   OP + = (VEC a, b) VEC: (x OF a + x OF b, y OF a + y OF b, z OF a + z OF b);
   OP - = (VEC a, b) VEC: (x OF a - x OF b, y OF a - y OF b, z OF a - z OF b);
   OP * = (REAL s, VEC v) VEC: (s * x OF v, s * y OF v, s * z OF v);
   OP * = (VEC a, b) REAL: x OF a * x OF b + y OF a * y OF b + z OF a * z OF b;   # dot product #
   OP ABS = (VEC v) REAL: sqrt(v * v);
   PRIO CROSS = 7;
   OP CROSS = (VEC a, b) VEC:
      (y OF a * z OF b - z OF a * y OF b,
       z OF a * x OF b - x OF a * z OF b,
       x OF a * y OF b - y OF a * x OF b);
   OP REPR = (VEC v) STRING:
      "(" + fixed(x OF v, 0, 2) + ", " + fixed(y OF v, 0, 2) + ", " + fixed(z OF v, 0, 2) + ")";

   VEC i = (1, 0, 0), j = (0, 1, 0);
   print((REPR (i + j), newline));
   print((REPR (i CROSS j), newline));       # (0, 0, 1) #
   print((ABS (2.0 * (i + j)), newline))
END

32.4 Assignment operators for your own modes

OP +:= = (REF VEC a, VEC b) REF VEC: a := a + b;
VEC pos := (0, 0, 0);
pos +:= (1, 2, 3);

32.5 Changing priorities

PRIO declarations apply in their range; you can redeclare the priority of an existing symbol in an inner range — legal but confusing; avoid.