On this page:
operator
8.16.0.2

4.4 Operators🔗ℹ

definition

operator op_case

 

definition

operator

| op_case

| ...

 

definition

operator op_or_id_name maybe_res_annot:

  option; ...

| op_case

| ...

 

op_case

 = 

op_or_id_name bind_term impl_block

 | 

bind_term op_or_id_name bind_term impl_block

 | 

bind_term op_or_id_name impl_block

 | 

(op_or_id_name bind_term) maybe_res_annot impl_block

 | 

(bind_term op_or_id_name bind_term) maybe_res_annot impl_block

 | 

(bind_term op_or_id_name) maybe_res_annot impl_block

 

impl_block

 = 

:

  case_option; ...

  body

  ...

 

case_option

 = 

option

 | 

~unsafe: unsafe_body; ...

 

option

 = 

~order name

 | 

~order: name

 | 

~stronger_than other ...

 | 

~stronger_than: other ...; ...

 | 

~weaker_than other ...

 | 

~weaker_than: other ...; ...

 | 

~same_as other ...

 | 

~same_as: other ...; ...

 | 

~same_on_left_as other ...

 | 

~same_on_left_as: other ...; ...

 | 

~same_on_right_as other ...

 | 

~same_on_right_as: other ...; ...

 | 

~associativity assoc

 | 

~associativity: assoc

 | 

~name op_or_id_name

 | 

~name: op_or_id_name

 | 

~who id

 | 

~who: id

 

other

 = 

id

 | 

op

 | 

~other

 

assoc

 = 

~left

 | 

~right

 | 

~none

 

bind_term

 = 

bind

Binds op_or_id_name as a operator, either prefix, infix, postfix, or a combination.

The operator is function-like in the sense that it receives argument values. (To bind an operator that is not function-like, see macro or expr.macro.) Each argument is specified by a binding that must be written as a single shrubbery term that is not an operator in the shrubbery sense; parentheses can be used around other binding forms for arguments. If two identifier terms appear within the parentheses that follow operator, a prefix operator is defined using the first identifier as its name. When a parenthesized sequence is followed by :: or :~, it is treated as starting a maybe_res_annot, which is the same as in fun definitions.

The new operator is also bound a repetition operator, in which case its arguments must be repetitions. The depth of the resulting repetition is the maximum of the argument repetition depths.

When multiple cases are provided via |, an operator can be defined as both prefix and infix or prefix and postfix (but not infix and postfix). The prefix cases and infix/postfix cases can be mixed in any order, but when the operator is used as a prefix or infix/postfix operator, cases are tried in the relative order that they are written. Similar to the fun form the operator name and a result annotation can be written before the | cases to apply for all cases.

At the start of an operator body, options can declare precedence, associativity (in the case of an infix operator), and/or naming options. Each option keyword can appear at most once. The ~order option selects a operator order for the operator, which defines precedence relationships to other operator orders and a default associativity, but precedence and associativity options with operator override the ones defined with the operator order. In a precedence specification, a name refers to another operator binding or to a operator order, while ~other stands for any operator not otherwise mentioned. The ~name, ~who, and ~unsafe options are as in fun. When multiple cases are provided using an immediate |, then only the first prefix case and the first infix/postfix case can supply options; alternatively, when the operator name (maybe with a result annotation) is written before |, options that apply to all cases can be supplied in a block before the cases. Options can appear both before the cases and in individual clauses, as long as all options of a particular kind are in one or the other.

operator x ^^^ y:

  x +& y +& x

> "a" ^^^ "b"

"aba"

> 1 ^^^ 2

"121"

operator x wings y:

  x +& y +& x

> "a" wings "b"

"aba"

operator ((x :: String) ^^^ (y :: String)) :: String:

  x +& y +& x

> "a" ^^^ "b"

"aba"

> 1 ^^^ 2

^^^: argument does not satisfy annotation

  argument: 1

  annotation: String

operator x List.(^^^) y:

  x ++ y ++ x

> block:

    import:

      .List open

    [1, 2] ^^^ [3]

[1, 2, 3, 1, 2]

operator

| x ^^^ y:

    x +& y +& x

| ^^^ y:

    "--" +& y +& "--"

> "a" ^^^ "b"

"aba"

> ^^^ "b"

"--b--"

operator ^^^:

  ~weaker_than: arithmetic

| x ^^^ y:

    x +& y +& x

| ^^^ y:

    "--" +& y +& "--"

> 1 ^^^ 2 + 3

"151"

> ^^^ 4 + 5

"--9--"