An assignment expression assigns a value to a named identifier (usually a variable).
The assignment operator is the equals sign (
The target of an assignment can be:
# Assigns to a local variable local = 1 # Assigns to an instance variable @instance = 2 # Assigns to a class variable @@class = 3 # Assigns to a constant CONST = 4 # Assigns to a setter method foo.method = 5 foo = 6
Method as assignment target¶
A method ending with an equals sign (
=) is called a setter method. It can be used
as the target of an assignment. The semantics of the assignment operator apply as
a form of syntax sugar to the method call.
Calling setter methods requires an explicit receiver. The receiver-less syntax
x = y
is always parsed as an assignment to a local variable, never a call to a method
Even adding parentheses does not force a method call, as it would when reading from a local variable.
The following example shows two calls to a setter method in typical method notation and with assignment operator. Both assignment expressions are equivalent.
class Thing def name=(value); end end thing = Thing.new thing.name=("John") thing.name = "John"
The following example shows two calls to an indexed assignment method in typical method notation and with index assignment operator. Both assignment expressions are equivalent.
class List def =(key, value); end end list = List.new list.=(2, 3) list = 3
Combined assignments are a combination of an assignment operator and another operator. This works with any target type except constants.
Some syntax sugar that contains the
= character is available:
local += 1 # same as: local = local + 1
This assumes that the corresponding target
local is assignable, either as a variable or via the respective getter and setter methods.
= operator syntax sugar is also available to setter and index assignment methods.
&& use the
? method to check for key presence.
person.age += 1 # same as: person.age = person.age + 1 person.name ||= "John" # same as: person.name || (person.name = "John") person.name &&= "John" # same as: person.name && (person.name = "John") objects += 2 # same as: objects = objects + 2 objects ||= 2 # same as: objects? || (objects = 2) objects &&= 2 # same as: objects? && (objects = 2)
The same value can be assigned to multiple targets using chained assignment. This works with any target type except constants.
a = b = c = 123 # Now a, b and c have the same value: a # => 123 b # => 123 c # => 123
You can declare/assign multiple variables at the same time by separating expressions with a comma (
This works with any target type except constants.
name, age = "Crystal", 1 # The above is the same as this: temp1 = "Crystal" temp2 = 1 name = temp1 age = temp2
Note that because expressions are assigned to temporary variables it is possible to exchange variables’ contents in a single line:
a = 1 b = 2 a, b = b, a a # => 2 b # => 1
If the right-hand side contains just one expression, the type is indexed for each variable on the left-hand side like so:
name, age, source = "Crystal, 123, GitHub".split(", ") # The above is the same as this: temp = "Crystal, 123, GitHub".split(", ") name = temp age = temp source = temp
Multiple assignment is also available to methods that end with
person.name, person.age = "John", 32 # Same as: temp1 = "John" temp2 = 32 person.name = temp1 person.age = temp2
And it is also available to index assignments (
objects, objects = 3, 4 # Same as: temp1 = 3 temp2 = 4 objects = temp1 objects = temp2
The underscore can appear on the left-hand side of any assignment. Assigning a value to it has no effect and the underscore cannot be read from:
_ = 1 # no effect _ = "123" # no effect puts _ # Error: can't read from _
It is useful in multiple assignment when some of the values returned by the right-hand side are unimportant:
before, _, after = "main.cr".partition(".") # The above is the same as this: temp = "main.cr".partition(".") before = temp _ = temp # this line has no effect after = temp