2013-03-19 3 views
0

Я заметил, изучая Ruby, что оба этих метода использования каждого метода работают и производят один и тот же вывод, и мне было интересно, как это делает Ruby (и как я могу это сделать для моих собственных функций):Ruby: Перегрузка Функция вывода

my_array = [["hello","goodbye"],["picture","perfect"]] 

my_array.each do |array| 

    puts array[0] + " " + array[1] 

end 

my_array.each do |first, second| 

    puts first + " " + second 

end 

Я понимаю, что при написании определения метода, который принимает блок кода, метод доходности используются для передачи аргументов в блок кода и вызвать блок. Но как вы можете использовать метод yield так, чтобы он передавал разные аргументы в зависимости от предоставленного кодового блока? В примере примера оказывается, что метод yield передает отдельные элементы массива, когда в блоке используются два параметра (т. Е. Первый, второй), и он передает сами массивы, когда один параметр используется внутри блока (т. Е. Массив).

+0

@ RoneyMichael Исправьте меня, если я ошибаюсь, но я не думаю, что это решение. Оператор splat предназначен для использования с параметрами, а не с аргументами. И мой вопрос касается того, как я структурирую свои операторы yield и какие аргументы передаю им. – voltair

+0

О, верно! Виноват. –

ответ

1

Ни each не yield ничего особенного здесь не делают, так работают блочные аргументы. Рассмотрим простой пример:

def f(x) yield x end 

и теперь мы можем увидеть, что происходит:

>> f([1,2]) { |a| puts a.inspect } 
[1, 2] 
>> f([1,2]) { |a, b| puts "#{a} - #{b}" } 
1 - 2 
>> f([1,2]) { |a, b, c| puts "#{a} - #{b} - #{c}" } 
1 - 2 - 

Вы увидите подобную разрушающие в назначениях:

a, b = [1, 2] 

Вы также можете сделать это в явном виде с a знак:

a, b = *[1, 2] 

или как это:

def g(x) yield *x end 
g([1, 2]) { |a, b| puts "#{a} - #{b}" } 

Предположительно блок знает, что сортирует вещи, это будет дано поэтому блок хорошо подходят для распаковки аргументов. Обратите внимание, что функция g должна знать, что ее аргумент является разделяемым (т. Е. Массивом), но f этого не делает. f красиво ставит «что-то типа x» логика вместе в вызове f, g погревает половину логики внутри себя. Одно место, где разница становится очевидной, когда вы используете перечислимых методы на Hash:

{ :where => :is, :pancakes => :house? }.map { |k, v| ... } 

Enumerable#map не нужно знать, что Hash работает в ключ/значение двух элементов массива, он просто пропускает вещи вокруг и листья это все остальные, чтобы беспокоиться о деталях.

+0

Большое вам спасибо за ваш ответ. так же есть место, где я могу видеть правила того, как рубин автоматически обнаруживает и деконструирует (или не деконструирует) эти объекты (например, массивы и хэши)? или это то, что вы просто изучаете с помощью проб и ошибок, поскольку это действительно похоже на массивы и хеши? также, для g-метода, соответствует ли знак в вашей функции yield ошибкой, если аргумент, переданный g, не является массивом? и доступны ли только массивы? это было то, что вы вынесли, но я не был уверен. – voltair

+0

@ user1419674: Только массивы получают автоматическое разбиение/деструктурирование в аргументах блока. Если вы хотите увидеть, как что-то взаимодействует с ['Enumerable'] (http://ruby-doc.org/core-2.0/Enumerable.html) (источник« карты »и друзей), вам нужно будет проверить документация класса. –

Смежные вопросы