Skip to content

Operators

Precedence Table

Seal follows almost exactly C's precende order for operators. Here is precedence table of Seal operators in descending order:

Operator(s) Description Associativity
++, --
()
[]
.
->
?
$
Postfix increment and decrement
Function call
Indexing
Field access
Method call
Safe access
Global variable access
Left-to-right
++--
+, -
 !,not, ~
Prefix increment and decrement
Unary plus and minus
Logical NOTs and bitwise NOT
Right-to-left
*, /, % Multiplication, division, and remainder Left-to-right
+, - Addition and subtraction
<<, >> Bitwise left shift and right shift
<<=
>>=
Less than and less than or equal to
Greater than and greater than or equal to
==, != Equal to and not equal to
& Bitwise AND
^ Bitwise XOR (exclusive OR)
\| Bitwise OR
and Logical AND
or Logical OR
if then else Ternary Right-to-left
=
*=, /=, %=
+=, -=
<<=, >>=,
&=, ^=, \|=
Simple assignment
Assignment by product, quotient, and remainder
Assignment by sum and difference
Assignment by bitwise left shift and right shift
Assignment by bitwise AND, XOR, and OR
, Comma Left-to-right

Some notes

  • ++, -- are just like in C. If it is postfix, it mutates variable afterwards, otherwise, it mutates right before giving value.
a = 32
print(a++) //  32
print(a)   //  33
print(++a) //  34
print(a)   //  34
  • $ lets you access to a global symbol explicitly. It is must be used if mutation or declaration of a global symbol is desired.
$a = 20   //  global
a  = 30   //  local, since on assignment, globals must be explicit
print(a)  //  30, if no '$', locals are searched first
print($a) //  20, since it is explicitly referred to a global

Now, what if no locals shadow a global?

$GLOBAL = 20
GLOBAL + 2  // we can omit '$' since there is no GLOBAL
            // in this scope
// this is just how global "print" function works without '$'
print("Hello, Seal!")
$print("Hello, Seal!")
// they are just the same

In Lua, everything you type without local is declared as a global. You have to type local to declare a local variable. But in Seal, it is kind of vice versa: unless you type $ explicitly, anything is local.

  • ? shall be combined with either field access operator (.) or on a variable directly.
WIDTH   //  if not defined, the program will crash
WIDTH?  //  if not defined, return null, otherwise its value

if not WIDTH?  //  one of its useful cases
    WIDTH = 1920

In Lua, if you type an undefined variable name, it will silently return nil, unless you have attached some metatable to _G global table (it is dirty in my opinion). But in Seal, as you can see, you can use ? operator to safely access to your global variable or just omit ? to catch typos in your program.

city = {
    name = "Vienna"
}

city.population   // crashes
city.population?  // null

// a useful case
population = city.population? or 30000

Another Lua vs Seal situtation here. In Lua, it doesn't crash when you access to undefined field of a map. But in Seal, you can define the access behavior.

  • -> is used as "method caller". Since Seal is a non-object-oriented language, this operator is used to imitate method-calling just like : operator in Lua.
person = {
    name = "Huseyn",
    talk = define(self, msg) print(self.name, ":", msg)
}

person->talk("Hello")

This is also useful on calling string, list functions as methods.

"hello"->upper()  //  "HELLO"
[]->push(0, 1, 2)

You can omit parentheses if you call with no arguments.

"hello"->upper()  //  omit ()
"hello"->upper
"hello"->len
  • Ternary operator in Seal is written in the following way:
a = if 5 > 1 then "hi" else "bye"
  • Seal uses , operator from C. It is not that widely known or talked about. It can be described as a "expression-separator". It evaluates expressions from left to right and returns the last expression value. So it is neither a tuple like in Python, nor multiple-returned value from a function in Lua.
a = "hi", "hello"  //  returns "hello"

Don't worry. Inside list and map declarators, function calls, and lambda, unless parentheses are explicitly put, comma is used as a separator, not operator.

func(1, 2) // separator, two arguments
func((1, 2)) // one argument, comma operator
list = [1, 2] // two elements
list = [(1, 2)] // one element, [2]
lambda = define(x) x * x, 2  //  lambda = 2
lambda = define(x) (x * x, 2)  //  lambda = a function that
                               //  that returns only 2