Рубиновый блок изворотливый.
Правило такое, если блок принимает более одного аргумента, и он дает один объект, который отвечает на to_ary
, тогда этот объект расширяется. Это приводит к тому, что массив в сравнении с получением кортежа, похоже, ведет себя одинаково для блоков, которые принимают два или более аргумента.
yield [a,b]
по сравнению с yield a,b
действительно отличаются друг от друга, если блок принимает только один аргумент или когда блок принимает переменное количество аргументов.
Позвольте мне продемонстрировать, как из того, что
def yield_tuple
yield 1, 2, 3
end
yield_tuple { |*a| p a }
yield_tuple { |a| p [a] }
yield_tuple { |a, b| p [a, b] }
yield_tuple { |a, b, c| p [a, b, c] }
yield_tuple { |a, b, c, d| p [a, b, c, d] }
гравюр
[1, 2, 3]
[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, nil]
В то время как
def yield_array
yield [1,2,3]
end
yield_array { |*a| p a }
yield_array { |a| p [a] }
yield_array { |a, b| p [a, b] }
yield_array { |a, b, c| p [a, b, c] }
yield_array { |a, b, c, d| p [a, b, c, d] }
печатает
[[1, 2, 3]]
[[1, 2, 3]]
[1, 2] # array expansion makes it look like a tuple
[1, 2, 3] # array expansion makes it look like a tuple
[1, 2, 3, nil] # array expansion makes it look like a tuple
И, наконец, чтобы показать, что все в Ruby, использует утку-печатая
class A
def to_ary
[1,2,3]
end
end
def yield_arrayish
yield A.new
end
yield_arrayish { |*a| p a }
yield_arrayish { |a| p [a] }
yield_arrayish { |a, b| p [a, b] }
yield_arrayish { |a, b, c| p [a, b, c] }
yield_arrayish { |a, b, c, d| p [a, b, c, d] }
отпечатки
[#<A:0x007fc3c2969190>]
[#<A:0x007fc3c2969050>]
[1, 2] # array expansion makes it look like a tuple
[1, 2, 3] # array expansion makes it look like a tuple
[1, 2, 3, nil] # array expansion makes it look like a tuple
PS такое же поведение расширения массива применяется для proc
замыканий, которые ведут себя как блоки, в то время как lambda
замыкания ведут себя как методы.
Это похоже на (может быть, такое же?), что происходит с параллельным назначением переменных из массива. См. Https://stackoverflow.com/questions/14913765/why-does-ruby-parallel-assignment-with-array-of-strings-returns-string – Max