Skip to content

In U, operators are functions too. Any function can be used as an infix operator. For example, plus + can be called with dot-notation like 10 + 1.

Operations

In U, an operator is a combination of the following characters:

! # $ % & * + - . / : < = > ? @ ^ | ~

The first character cannot be an Aperture.

Functions identified with operators are called operations.

Operators can be used to form expressions. U has all common operators inherited from C family languages necessary to build correct applications:

  • arithmetic: add +, inc ++, divide /...
  • logical: not !, or ||, and &&, ...
  • bitwise: or |, and &, ...
  • comparison: less than <, greater than >, ...

All operator have their keywords equivalent:

  • ||: logical ::or,
  • | : bitwise ::bor
  • ...

Operator type

U supports the following operator type:

  • prefix: before values like ++a,
  • unary postfix: after values like a++, or a.* 3,
  • binary postfix: after values like an iterator a.* 3,
  • infix: between two values like 1 + 2,
  • head: at the beginning of a statement
    - a, b
    
  • tail: at the end of a statement
    << a, b  #>  # '#>' is a tail operator
    

Equality and Comparison

There are two equality operator types. If you think of values as boxes, then:

  • structural equality ==, !=:

    • Compare the content of two boxes: compare its memory content.
    • Most common use case
  • referential equality ===, !==:

    • Compare two boxes: checks if both values point to the same memory location.
    • To avoid unless necessary. It requires familiarity with the implementation as mutable and immutable value locations are freely modified by the compiler even during program execution.
    • Mostly used when working on low-level systems.

For example:

:a : 'Welcome'
:b : 'Welcome'

\< a == b
# ALWAYS Prints 'true'

:c : 'Welcome Home'
:d : c[0:.:6]@String # <d> <=> 'Welcome'

\< a === b
# Prints 'true', U optimize strings with same content

\< a === d
# Prints 'false', U keep <d> as a slice, 

However, if d is only used as a string in the source code:

  • d will be converted to a String type,
  • a === d will be true

It's the reason why referential equality is to avoid unless necessary.

Mutable values are equal if their current contents are structurally equal, even if the two mutable values are not the same physical object.

Equality Comparison Failure

Equality Comparison may fail in the following cases:

  • Equality between functional values,
  • Equality between cyclic classes may not terminate.

Predefined Operators

See Predefined Operators.

Additional parameters

As a + b gets converted to + a, b, you can add additional parameters:

:a : %! "hello"
a <<=(3) '!' # Same as append(a, '!', 3)
# Prints "hello!!!"

If <<= exists as a prefix operator, U raises an error.

Defining operators

U allows you to define your own operator too.

# Add infix operator '**', with precedence higher than multiplication '*'
Number::infix :'<+>', %prec{> *}, {: right-hand-side
    :r : ::self + right-hand-side
    \< "<+> called => \:r"
    r
}

\< 2 <+> 2 
# Prints "<+> called => 4"