Operators

You can define custom operators in prelude global to all modules, or define them locally in you module for your module only.

Some of the operators like :: . : and or -> # are declared internally and have special meaning for compiler

All defined operators in prelude

// first name is operator, second is function which be used by compiler and third is precedence
// right binding
infixr (:=, :=, 10)

// internal infix as of precedence 15

infixr (<-, <-, 15)
infixr (!, __send__, 15) // sending message
infixl (<|, <|, 15) // pipe left
infixl (|>, |>, 20) // pipe right

// internal infix or precedence 25

infixl (<<, <<, 25) // func composition left
infixl (>>, >>, 25) // func composition right

// internal infix and precendece 30

infixl (<, <, 35)
infixl (>, >, 35)
infixl (>=, >=, 35)
infixl (<=, <=, 35)
infixl (==, ==, 35)
infixl (!=, !=, 35)
infixl (++, ++, 40)
infixl (+, +, 40)
infixl (-, -, 40)
infixl (*, *, 50)
infixl (/, /, 50)

// prefix operator
// cannot use - it is set for infix operator
// use qualified name to prevent infinite loops in cases of declaring local negate function using prefix -
prefix (-, arza:negate, 55)

// internal infix :: precedence 60

infixl (**, **, 60) // pow

// internal prefix # precedence 70

prefix (&, &, 70) // deref
prefix (&&, &&, 70) //deref deref
infixl (.., .., 90) // carrying

// internal infix (  .{ .[ precedence 95

prefix (~, ~, 96) // carried function

// internal infix . : precedence 100

Later you must create functions for declared operators like

fun |>(x, f) = f(x)
fun <|(f, x) = f(x)
fun >>(f, g) = x -> g(f(x))
fun <<(f, g) = x -> f(g(x))
// ... and others

When Arza parses expression 1 + 2 it compiles it to +(1, 2).

The same with prefix operator. Expression -1 will be transformed into arza:negate(1)

Special operators

  • infix operator : like in module:function() treats by compiler as exported name and as path separator in import include expressions

    import my:modules:module1
    let three = module1:add(1, 2)
    
  • infix operators and or are compiled into jump instructions

  • infix operator -> creates lambda functions like (x, y) -> x + y

  • infix operator :: compiles into call cons(left, right) in expressions and receives special treatment in pattern matching

  • infix operator of compiles into call kindof(left, right) in expressions and receives special treatment in pattern matching

  • infix operator as compiles into call cast(left, right) in expressions and receives special treatment in pattern matching

  • infix operator . like in left.right compiles into at(left, #right) where #right is symbol

  • infix operator .[ like in left.[right] compiles into at(left, right) where right is any expression

  • infix operator .{ like in left.{key=value} compiles into put(left, #key, value). If key is enclosed in parens like left.{(key) = value} it compiles to put(left, key, value).

    let x = {x=1, (1+2)=2}
    let x1 = x.{x=2, (True)=2, (4-1)=2, "key"="value"}
    
  • infix operator ( like in myfunc(ar1, arg2) compiles into special bytecode instruction and receives special treatment in pattern matching

  • infix operator { like in MyType{key1=value1, key2} receives special treatment in pattern matching

  • infix operator | delimits clauses in pattern matching

  • prefix operator not compiles into special instruction

  • prefix operator # like in #I_AM_SYMBOL constructs symbols in expressions and in match clauses

  • prefix operator ... like in [x, x1, ...xs] and myfunc(...varargs) receives special treatment in pattern mathing and in function calls

match [1, 2, 3]
| [head, ...tail]

fun f(...args) =
    //calling other func
    // ...args flush sequence into call arguments
    f2(1, 2, ...args, 3, 4)

Functions as infix operators

To call function as infix operator enclose it in ``.

Such function operator will have precedence 35

mymap `has` #key
i `kindof` Int
1 `add` 2