Присваивание
Выражение присваивания присваивает значение именованному идентификатору (обычно переменной). Оператор присваивания — это знак равенства (=).
Целью присваивания может быть:
- локальная переменная
- переменная экземпляра
- переменная класса
- константа
- метод присваивания
# 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[0] = 6
Метод в качестве цели присваивания
Метод, имя которого заканчивается знаком равенства (=), называется методом-сеттером. Его можно использовать в качестве цели присваивания. Семантика оператора присваивания применяется как синтаксический сахар для вызова метода.
Для вызова методов-сеттеров требуется явный получатель. Синтаксис без получателя x = y всегда разбирается как присваивание локальной переменной, а не как вызов метода x=. Даже добавление скобок не заставляет интерпретировать выражение как вызов метода, как это происходит при чтении локальной переменной.
В следующем примере показаны два вызова метода-сеттера: в обычной записи метода и с оператором присваивания. Оба выражения присваивания эквивалентны.
class Thing
def name=(value); end
end
thing = Thing.new
thing.name=("John")
thing.name = "John"
В следующем примере показаны два вызова метода индексированного присваивания: в обычной записи метода и с оператором индексированного присваивания. Оба выражения присваивания эквивалентны.
class List
def []=(key, value); end
end
list = List.new
list.[]=(2, 3)
list[2] = 3
Составные присваивания
Составные присваивания сочетают оператор присваивания с другим оператором. Они работают с любым типом цели, кроме констант.
Доступен синтаксический сахар с символом =:
local += 1 # same as: local = local + 1
Предполагается, что соответствующей цели local можно присвоить значение — напрямую как переменной либо через соответствующие методы чтения и записи.
Синтаксический сахар для оператора = также доступен для методов-сеттеров и методов индексированного присваивания. Обратите внимание, что || и && используют метод []? для проверки наличия ключа.
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[1] += 2 # same as: objects[1] = objects[1] + 2
objects[1] ||= 2 # same as: objects[1]? || (objects[1] = 2)
objects[1] &&= 2 # same as: objects[1]? && (objects[1] = 2)
Цепочечное присваивание
Одно и то же значение можно присвоить нескольким целям с помощью цепочечного присваивания. Оно работает с любым типом цели, кроме констант.
a = b = c = 123
# Now a, b and c have the same value:
a # => 123
b # => 123
c # => 123
Множественное присваивание
Можно объявить или присвоить значения нескольким переменным одновременно, разделив выражения запятой (,). Это работает с любым типом цели, кроме констант.
name, age = "Crystal", 1
# The above is the same as this:
temp1 = "Crystal"
temp2 = 1
name = temp1
age = temp2
Поскольку выражения присваиваются временным переменным, содержимое переменных можно обменять в одной строке:
a = 1
b = 2
a, b = b, a
a # => 2
b # => 1
Если правая часть содержит только одно выражение, тип индексируется для каждой переменной в левой части следующим образом:
name, age, source = "Crystal, 123, GitHub".split(", ")
# The above is the same as this:
temp = "Crystal, 123, GitHub".split(", ")
name = temp[0]
age = temp[1]
source = temp[2]
Множественное присваивание также доступно для методов, заканчивающихся на =:
person.name, person.age = "John", 32
# Same as:
temp1 = "John"
temp2 = 32
person.name = temp1
person.age = temp2
Оно также доступно для индексированных присваиваний ([]=):
objects[1], objects[2] = 3, 4
# Same as:
temp1 = 3
temp2 = 4
objects[1] = temp1
objects[2] = temp2
Подчёркивание
Подчёркивание можно использовать в левой части любого присваивания. Присваивание ему значения не оказывает эффекта, а прочитать его значение нельзя:
_ = 1 # no effect
_ = "123" # no effect
puts _ # Error: can't read from _
Оно полезно при множественном присваивании, когда некоторые значения, возвращаемые правой частью, не важны:
before, _, after = "main.cr".partition(".")
# The above is the same as this:
temp = "main.cr".partition(".")
before = temp[0]
_ = temp[1] # this line has no effect
after = temp[2]
To the extent possible under law, the persons who contributed to this workhave waived
all copyright and related or neighboring rights to this workby associating CC0 with it.
https://crystal-lang.org/reference/1.2/syntax_and_semantics/assignment.html