Fuzion Logo
fuzion-lang.dev — The Fuzion Language Portal

Operator Calls

In Fuzion, the application of operators like + is merely syntax sugar for calling features. Every application of an operator can be converted to an equivalent feature call using dot notation a.f b. Problems that need to be solved are handling of names and operator overloading. E.g., - could be used as an infix a-b, prefix -a or postfix a- operator.

Operator calls in other languages

C#

C# permits user code to overload a subset of the predefined prefix, postfix and infix operators. Operator calls like a & b can be written like static dot-calls T.&(a,b). C# has special handling for boolean operators allowing arbitrary types to be used as booleans.

Java

Java does not support methods to be called using operator syntax. Operators are for built-in operations only. This is a main reason for Java being known for its heavy boilerplate.

Operators in Fuzion

Operator and method names

In Fuzion, operators always have an equivalent method name that can be used in a dot-call.

Operator dot-call name comment
a*b
        
a.infix * b
        

infix operators

-a
        
a.prefix -
        

prefix operators

a!
        
a.postfix !
        

postfix operators

a ? b : c
        
a.ternary ? : b c
        

This is a bit hard for the parser to distinguish from match-expression

a ? x X => f
  | y Y => g
        

TBD: This might be removed once match-expressions' syntax sugar is more powerful.

a[i,j]
        
a.index [] i j
        

index operator

a[]
        
a.index []
        

index operator may have no arguments

a[i,j] := b
        
a.set [] i j b
        

set index operator

not supported yet:

a.n := b
        
a.set n b
        

TBD: Is this useful?

Operators and argument counts

In Fuzion, every feature has an implicit argument that is passed as the outer instance in a call. Additionally, there might be any number of type parameters in addition to the value arguments. This raises the question how many arguments operator calls should have? E.g, in an infix call l <op> r, which role will l and r take?

In Fuzion, an infix operator can be defined with one value argument. This means that the left hand side of a call becomes the target of the call:

# A very shabby implementation of roman numerals supporting addition:
#
number(s String) is
v := s.replace "IIIII" "V"
.replace "VV" "X"
# an infix operator with one explicit argument, i.e., the left
# hand side will become the target (number.this)
#
infix + (o number) => number (v + o.v)
public redef as_string => v
three := number "III"
two := number "II"
five := three + two
eight := five + three
thirteen := five + eight
say "$three + $two is $five"
say "$five + $eight is $thirteen"
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Alternatively, an infix operator defined with two value arguments can be called as an operator only where the unqualified operator is visible, the target will be added implicitly:

# A very shabby implementation of roman numerals supporting addition:
#
number(s String) is
v := s.replace "IIIII" "V"
.replace "VV" "X"
public redef as_string => v
# an infix operator with two explicit arguments, i.e., the left
# hand side will become the first argument adn the right hand side
# will become the second:
#
infix + (a, b number) => number (a.v + b.v)
three := number "III"
two := number "II"
five := three + two
eight := five + three
thirteen := five + eight
say "$three + $two is $five"
say "$five + $eight is $thirteen"
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Similarly, a prefix or postfix operator can be defined with one value argument:

# postfix operator to print a value and its type and return the value
#
postfix !!! (A type, a A) => { say "debug $a, $A"; a }
(say (123!!! + 456!!!).as_string!!!)!!!
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Operator calls and type parameters

Operator calls may have an arbitrary number of type parameters. However, it must be possible to infer their values from the actual value arguments. There will be no direct way to specify a type parameter when used as an operator.

# infix operator to create a tuple (a, b) of types i32 and bool
#
infix +-+ (a i32, b bool) => (a, b)
t := 34 +-+ true
say t.0
say t.1
# infix operator with type parameters to create a tuple (a, b)
# of arbitrary types
#
infix -+- (A, B type, a A, b B) =>
say "creating tuple of $A and $B"
(a, b)
u := "string" -+- 3.14
say u.0
say u.1
v := t -+- u
say v.0
say v.1
# to specify explicit types, we must call by name:
w := infix -+- u8 (option bool) 11 false
say w.0
say w.1
x := infix -+- u16 (outcome bool) 11 false
say x.0
say x.1
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
last changed: 2024-06-28