# Operators
Operators are natural building blocks of languages, so it's no surprise ABS has its fair share of them.
As a general rule, you should understand that ABS does not allow to use operator on different types, with a couple exceptions. Here is a list of operators you can use, with examples on how to make the most out of them.
# ==
Equality operator, one of the few that can be used between arguments of different type:
1 == 1 # true
1 == "hello world" # false
# !=
Not equals operator, one of the few that can be used between arguments of different type:
1 != 1 # false
1 != "hello world" # true
# +
Addition, can be used to merge arrays and combine strings as well:
1 + 1 # 2
"hello" + " " + "world" # "hello world"
[1] + [2] # [1, 2]
# +=
Compound addition:
a = 10
a += 1 # a is now 11
# -
Subtraction:
0 - 1 # -1
# -=
Compound subtraction:
a = 10
a -= 1 # a is now 9
# *
Multiplication:
1 * 2 # 2
# *=
Compound multiplication:
a = 10
a *= 10 # a is now 100
# /
Division:
5 / 5 # 1
# /=
Compound division:
a = 10
a /= 2 # a is now 5
# in
Membership test operator (find whether a needle is in the haystack):
1 in [1, 2, 3] # true
9 in [1, 2, 3] # false
9 in 9 # unknown operator: NUMBER in NUMBER
"str" in "string" # true
"xyz" in "string" # false
"x" in {"x": 1} # true
"y" in {"x": 1} # false
# !in
Negative membership test operator (find whether a needle is not in the haystack):
1 !in [1, 2, 3] # false
9 !in [1, 2, 3] # true
9 !in 9 # unknown operator: NUMBER in NUMBER
"str" !in "string" # false
"xyz" !in "string" # true
"x" !in {"x": 1} # false
"y" !in {"x": 1} # true
# **
Mathematical exponentiation:
2 ** 2 # 4
2 ** 0 # 1
# **=
Compound exponentiation:
a = 10
a **= 0 # a is now 1
# %
Modulo:
19 % 5 # 4
# %=
Compound modulo:
a = 19
a %= 5 # a is now 4
# >
Greater than:
10 > 0 # true
0 > 10 # false
When used with strings, >
redirects
the input (left argument) to a file
(right argument):
"Hi, there" > "file.txt"
`cat /etc/hosts` > "copy-of-etc-hosts.bkp"
# >=
Greater or equal than:
1 >= 1 # true
2 >= 1 # true
# <
Lower than:
10 < 0 # false
0 < 10 # true
# <=
Lower or equal than:
1 <= 1 # true
1 <= 2 # true
# <=>
The combined comparison operator allows to test whether a number is lower, equal or higher than another one with one statement:
5 <=> 5 # 0
5 <=> 6 # -1
6 <=> 5 # 1
# &&
Logical AND, which supports short-circuiting (opens new window):
true && true # true
true && false # false
1 && 2 # 2
1 && 0 # 0
0 && 2 # 0
"" && "hello world" # ""
"hello" && "world" # "world"
# ||
Logical OR, which supports short-circuiting (opens new window):
true || true # true
true || false # true
1 || 2 # 1
1 || 0 # 1
"" || "hello world" # "hello world"
"hello" || "world" # "hello"
# .
Property accessor, used to access properties or methods of specific variables:
hello = {"to_who": "the world"}
hello.to_who # "the world"
There are some builtin functions that you can access through the property accessor:
"hello".len() # 5
(a comprehensive list of function is documented in the "Types and functions" section of the documentation)
# ?.
Optional chaining operator, used to access properties in a "safe" way.
Given the following object:
test = {"property": 1}
An error would be raised if you were trying to access a non-existing property
such as test.something.something_else
:
ERROR: invalid property 'something_else' on type NULL
[1:15] test.something.something_else
Optional chainig prevents those errors from being raised, auto-magically
converting non-existing properties and methods to NULL
:
test?.something?.something_else # null
test?.something?.something_else() # null
# ..
Range operator, which creates an array from start to end:
1..10 # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
10..1 # [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
# !
Negation:
a = true
!a # false
# !!
Even though there is no double negation operator, using 2 bangs will result into converting the argument to boolean:
!!1 # true
!!0 # false
!!"" # false
!!"hello" # true
# ~
The tilde (meaning "around") is used to do similarity comparisons (x "is almost" y).
In case of strings, it will compare them case-insensitively
"hello" == "HELLO" # false
"hello" ~ "HELLO" # true
In case of integers, it will compare their integer values:
1 == 1.5 # false
1 ~ 1.5 # true
When in front of a number, it will instead be used as a bitwise NOT:
~0 # -1
~"hello" # ERROR: Bitwise not (~) can only be applied to numbers, got STRING (hello)
# &
Bitwise AND:
1 & 1 # 1
1 & "hello" # ERROR: type mismatch: NUMBER & STRING
# |
Bitwise OR:
1 | 1 # 1
1 | "hello" # ERROR: type mismatch: NUMBER | STRING
# ^
Bitwise XOR:
1 ^ 1 # 0
1 ^ "hello" # ERROR: type mismatch: NUMBER ^ STRING
# >>
Bitwise right shift:
1 >> 1 # 0
1 >> "hello" # ERROR: type mismatch: NUMBER >> STRING
When used with strings, >>
appends
the input (left argument) to a file
(right argument):
"Hi" >> "file.txt"
" " >> "file.txt"
"there!" >> "file.txt"
`cat file.txt` # Hi there!
# <<
Bitwise left shift:
1 << 1 # 2
1 << "hello" # ERROR: type mismatch: NUMBER << STRING