Operators

!

Usage:

!x

Returns:

1 if x is falsy (null, 0, or ''), 0 if it is not

!=

Usage:

x != y

Returns:

1 if x is not equal to y, 0 if it is

To check inequivalence, use the ~! operator.

This can otherwise be specified as the <> operator.

%

Usage:

x % y

Returns:

The remainder of x / y

This operator only works with integer values - with x and y being truncated to integers prior to the remainder being calculated. Fractional modulo can be achieved using the %% operator.

%%

Usage:

x %% y

Returns:

The remainder of x divided by y

This is used to calculate fractional modulo calculations, unlike the % operator which only works on integers. It is equivalent to y * fract(x / y).

%%=

Usage:

x %%= y

Assigns x to the value of x %% b. It is equivalent to x = x %% b.

This is fractional modulo, which is the remainder value of x divided by b. For integer values only, you can use %=.

%=

Usage:

x %= y

Assigns x to the value of x % y. It is equivalent to x = x % y.

This is integer modulo, where x and y are truncated to integers prior to the remainder of x divided by y being taken. For fractional values, use %%=.

&

Usage:

x & y

Returns:

The binary AND of x and y

If x and y are /lists, the result is a list which contains items present in both x and y, in the order they were in in list x.

&&

Usage:

x && y

Returns:

True value if x and y are both truthy, or the first falsy value encountered.

The return value is the last argument to be evaluated. The first falsy value from left to right will short-circuit the expression, and the rest of the expression will not be evaluated.

var/foo = FALSE && blow_up_the_world()

This code will never end up blowing up the world, as when evaluating the expression, it will stop after the first falsy value (in this case, FALSE).

&=

Usage:

x &= y

Assigns x to the value of x & b. It is equivalent to x = x & b. This is often used for disabling bitflags in a bitfield.

#define MY_BITFLAG (1<<0)

var/my_field = MY_BITFLAG // starts enabled
my_field &= ~MY_BITFLAG // now disabled

If both x and y are /lists, items in x that are not present in y will be removed.

var/list/a = list("foo")
var/list/b = list("bar")

a &= b

world.log << json_encode(a) // empty list!

*

Usage:

x * y

Returns:

The product of x multiplied by y.

x can be a /matrix, which results in a new matrix. y can be a number, which will change the scale of the matrix, or another matrix.

**

Usage:

x ** y

Returns:

x to the power of y

*=

Usage:

x *= y

Assigns x to the value of x * y. It is equivalent to x = x * y.

++

Usage:

++x (pre-increment), x++ (post-increment)

The pre-increment has the value of x + 1, and adds 1 to x.

The post-increment has the value of x, and then adds 1 to x.

var/x = 0
world.log << ++x // 1
world.log << x++ // 1
world.log << x // 2

+=

Usage:

x += y

Assigns x to the value of x + y. It is equivalent to x = x + y.

-

Usage:

x - y, or -y

Returns:

If x is a:
- number, returns x minus y.
- list, a new list with y removed from the contents of x. If y is also a list, where the contents are in both lists, they will be removed from the new list.
- matrix, and y is a matrix, a new matrix with their components subtracted.

--

Usage:

--x (pre-decrement), x-- (post-decrement)

The pre-decrement has the value of x - 1, and subtracts 1 from x.

The post-decrement has the value of x, and then subtracts 1 from x.

var/x = 1
world.log << --x // 0
world.log << x-- // 0
world.log << x // -1

-=

Usage:

x -= y

Assigns x to the value of x - y. It is equivalent to x = x - y.

.

This is used to access the properties (procs and vars) of an object. This checks at compile time to see if the property being accessed does exist on the type of variable provided, providing build-time safety over the : (colon) operator.

var/mob/my_mob = new /mob()
my_mob.name = "Barry"

This successfully compiles and does not generate a runtime, as the type is correctly cast to /mob, and the prototype in the variable is also a /mob.

var/mob/my_mob
my_mob.name = "Evil Barry"

This code also successfully compiles, as the type is correctly cast to /mob, which has an inherited variable called /atom/var/name. However, there is no /mob object assigned to the variable, so it will result in a runtime error.

/

Usage:

x / y

Returns:

x divided by y

x can be a /matrix, which results in a new matrix. y can be a number, which will change the scale of the matrix, or another matrix.

/=

Usage:

x /= y

Assigns x to the value of x / y. It is equivalent to x = x / y.

:

This is used to access the properties of a variable that it is not necessarily cast as having. If the variable does not contain the specified property, a runtime error will occur.

var/foo = null

foo:name = "yay!"

This code compiles, however, upon execution of the code, it will error, as you cannot access the name var of null.

The . (dot) operator works the same way to access a variable's properties, however, it will check at compile time if the type the variable is cast as contains this property. This is preferred behavior - it is easier to catch errors in the compiler than at runtime.

<

Usage:

x < y

Returns:

1 if x is lesser than y, 0 otherwise

If both x and y are strings, they are compared case sensitively - see sortTextEx().

<<=

Usage:

x <<= y

Assigns x to the value of x << y. It is equivalent to x = x << y. The left shift operator is documented here.

<=

Usage:

x <= y

Returns:

1 if x is lesser or equal to y, 0 otherwise

If both x and y are strings, they are compared case sensitively - see sortTextEx().

=

Usage:

x = y

Assigns the value of y to the variable x. These can be chained together:

x = y = z

Which results in x, y and z containing the same value.

==

Usage:

x == y

Returns:

1 if x and y are equal, 0 otherwise

To check for equivalence, you can use the ~= operator.

>

Usage:

x > y

Returns:

1 if x is greater than y, 0 otherwise

If both x and y are strings, they are compared case sensitively - see sortTextEx().

>=

Usage:

x >= y

Returns:

1 if x is greater or equal to y, 0 otherwise

If both x and y are strings, they are compared case sensitively - see sortTextEx().

>>=

Usage:

x >>= y

Assigns x to the value of x >> y. It is equivalent to x = x >> y. The right shift operator is documented here.

?

Usage:

x ? do_when_true() : do_when_false()

If x evaluates to a truthy value, do_when_true() will be evaluated and returned. Otherwise, do_when_false() will be evaluated and returned.

var/my_number = pick(1, 2)
world.log << my_number == 2 ? "My number was two!" : "My number was not two."

?.

Usage:

x?.property

This is used to access the properties of an object, like the . operator. However, using this operator, if the object is null, the access does not occur, and no runtime error will happen.

var/obj/my_thingy // not assigned to anything, so this will be null
my_thingy?.name = "Balloon" // as it is null, no access occurs, and no runtime occurs

var/obj/my_other_thingy = new /obj()
my_other_thingy?.name = "Runtime Damian" // as it is not null, and /obj has a member called name, the variable will be updated

This behavior is identical to the ?: operator, but that operator will not check at compile time if the property does exist for the provided variable type. As such, the ?. operator is generally preferred.

?:

Usage:

x?:property

This is used to access the properties of an object without compile time safety-checks, like the : operator. However, using this operator, if the object is null, the access does not occur, and no runtime error will happen.

var/my_thingy // not assigned to anything, so this will be null
my_thingy?:name = "Damian" // as it is null, no access occurs, and no runtime occurs

var/my_other_thingy = 1 // assigned to a truthy value
my_other_thingy?:name = "Runtime Damian" // as it is not null, access does occur, and 1 does not have a name variable, so a runtime occurs

This behavior is identical to the ?. operator, but that operator will check if the property is valid for the variable's type. As such, that operator is typically preferred, as it will provide compile-time errors.

?[]

Usage:

x?[y], where x is a list and y is an index/key

This is the null-safe indexing operator, where if the list is null, the indexing operation will not occur.

var/list/my_list = list("foo", "bar")
var/list/my_nonexistent_list

world.log << my_list?[1] // "foo"
world.log << my_list?[1] // nothing!

If there is an expression on the right hand side of the operator to be evaluated and the list is null, the expression will not be evaluated. This will only take place if the list can be indexed.

my_nonexistent_list?[1] = do_something() // the proc will not be called here
my_list?[1] = do_something() // but it will be called here

[]

Usage:

list[x]

This is used to access the element of lists with a given key or index.

var/list/my_list = list("foo")
world.log << my_list[1] // "foo"

var/list/my_other_list = list("key" = "bar")
world.log << my_other_list["key"] // "bar"

^

Usage:

x | y

Returns:

The binary XOR of x and y

If x and y are both /lists, the result is a list containing items that are in either list, but not in both lists. Items from only x will be first, followed by items from only list y.

^=

Usage:

x ^= y

Assigns x to the value of x ^ y. It is equivalent to x = x ^ y.

If x and y are both /lists, items found in both lists will be removed from x, and then only items present in y are added to x.

in

Usage:

x in list

Returns:

1 if x is in list, 0 otherwise

This is a null-safe way of checking if an item is in a list, unlike /list/proc/Find(), which will runtime error if the list is not defined.

To check if an item is not in a given list, you can check !(item in list). This is distinct from checking (!item in list), which would coerce item into 0 or 1, and check if 0 or 1 is in the list.

|

Usage:

x | y

Returns:

The binary OR of x and y

If x and y are both /lists, the result is a list containing items that are in either list. Items from list x will be first, followed by items from list y, if not present in x.

|=

Usage:

x |= y

Assigns x to the value of x | y. It is equivalent to x = x | y. This is often used for enabling bitflags in a bitfield.

#define MY_BITFLAG (1<<0)

var/my_field = 0 // starts disabled
my_field |= MY_BITFLAG // now enabled

If both x and y are /lists, all items in y not already present in x will be added to x.

||

Usage:

x || y

Returns:

True value if either x or y are truthy, or the last falsy value encountered.

The return value is the last argument to be evaluated. The first truthy value from left to right will short-circuit the expression, and the rest of the expression will not be evaluated.

var/foo = TRUE && launch_the_missiles()

The missiles will never be launched, as the expression will short-circuit after evaluating the first truthy value (in this case, TRUE).

~

Usage:

~x

Returns:

The bitwise complement/binary NOT of 'x'.

Parity Issue ⚠️
In the OpenDream implementation of DreamMaker, this feature differs in implementation:
Currently, /matrix does not support the usage of the binary NOT operator.

~!

Usage:

x ~! y

Returns:

1 if x and y are not equivalent, 0 otherwise

Equivalence is a less strict version of equality - see the ~= operator.

To check two items are not equal, use !=.

~=

Usage:

x ~= y

Returns:

1 if x and y are equivalent, 0 otherwise

Equivalence is less strict than equality, and these are equivalent, when they would not be equal:

  • two different /lists with the same contents,
  • two different /matrix with the same values,

For strict equality, use the == operator.