Ruby - переопределение/включение множественного присвоения (например, `a, b, c = d, e, f`)
В рубине вы можете сделать это:
d = [1, 2, 3]
a, b, c = d
a
, b
и c
будут получать значения 1, 2 и 3 соответственно.
d
, в этом случае в Array
и ruby знает, чтобы назначить его содержимому a
, b
и c
. Но если d
был Fixnum
, например, только a
было бы присвоено значение d
, а b
и c
было бы назначено nil
.
Какие свойства d
позволяют использовать его для множественного присвоения? В моем изучении до сих пор я смог сделать экземпляры подклассов Array
таким образом.
Ответы
Ответ 1
Это очень недокументированная функция, и я буду использовать ее с осторожностью, но здесь мы идем. Из книги "Язык программирования Ruby":
Когда имеется несколько значений l и Руби пытается попытаться расширьте rvalue в список значения для назначения. Если это значение массив, Ruby расширяет массив так, чтобы каждый элемент становится его собственным значением r. Если значение не является массивом, но реализует метод to_ary
, Ruby вызывает этот метод, а затем расширяется массив, который он возвращает.
В Ruby 1.8 это метод to_ary
, в документации Ruby 1.9 говорит, что он вызывает to_splat
, но я не тестировал (нет 1.9 в этой машине) Он didn работайте как ожидалось. Итак, вы должны определить метод to_ary
в вашем объекте.
class Week
def to_ary
%w(monday tuesday wednesday thursday friday saturday sunday)
end
end
mon, tue, wed, thu, *weekend = Week.new
* %w(...)
Является специальным обозначением для массива слов, если вы ленивы писать ['monday', 'tuesday' ...]
Ответ 2
Какие свойства d
позволяют использовать его для множественного присвоения?
d
должен быть Array
или быть конвертируемым в один. IOW это должен быть либо экземпляр класса Array
(или любого из его подклассов), либо отвечать на сообщение to_ary
:
def (not_an_array = Object.new).to_ary; [:foo, :bar, :baz] end
foo, bar, baz = not_an_array
foo # => :foo
bar # => :bar
baz # => :baz
Обратите внимание, что это экземпляр более общего шаблона в Ruby: почти все методы в Ruby, которые ожидают, что Array
, a String
, Integer
или Float
также будут принимать объект, который отвечает до to_ary
, to_str
, to_int
или to_float
. И ваши собственные методы тоже должны быть кстати!