Подтвердить что ты не робот

Передача лямбды в виде блока

Я пытаюсь определить блок, который я буду использовать для передачи каждого метода из нескольких диапазонов. Вместо того, чтобы переопределять блок в каждом диапазоне, я хотел бы создать lamba и передать лямбду как таковую:

count = 0
procedure = lambda {|v| map[count+=1]=v}
("A".."K").each procedure
("M".."N").each procedure
("P".."Z").each procedure

Однако я получаю следующую ошибку:

ArgumentError: wrong number of arguments(1 for 0)
    from code.rb:23:in `each'

Любые идеи, что здесь происходит?

4b9b3361

Ответ 1

Отметьте амперсанд (&) в аргументе, например:

("A".."K").each &procedure

Это означает, что вы передаете его как специальный параметр блока метода. В противном случае это интерпретируется как нормальный аргумент.

Он также отражает их способ захвата и доступа к параметру блока внутри самого метода:

# the & here signifies that the special block parameter should be captured
# into the variable `procedure`
def some_func(foo, bar, &procedure)
  procedure.call(foo, bar)
end

some_func(2, 3) {|a, b| a * b }
=> 6

Ответ 2

Трюк заключается в использовании &, который сообщает Ruby, чтобы преобразовать этот аргумент в Proc, если это необходимо, а затем использовать этот объект в качестве блока методов. Начиная с Ruby 1.9 есть ярлык для лямбда (анонимных) функций. Итак, вы можете написать код следующим образом:

 
(1..5).map &->(x){ x*x }
# => [1, 4, 9, 16, 25]

возьмет каждый элемент массива и вычислит его мощность

это то же самое, что и этот код:

func = ->(x) { x*x }
(1..5).map &func

для Ruby 1.8:

(1..5).map &lambda {|x| x*x}
# => [1, 4, 9, 16, 25]

Чтобы решить вашу проблему, вы можете использовать метод Array reduce (0 - начальное значение):

('A'..'K').reduce(0) { |sum,elem| sum + elem.size }
# => 11

Передача лямбда-функции на reduce немного сложна, но анонимный блок почти такой же, как лямбда.

('A'..'K').reduce(0) { |sum, elem| ->(sum){ sum + 1}.call(sum) }
# => 11

Или вы можете писать такие строки следующим образом:

('A'..'K').reduce(:+)
=> "ABCDEFGHIJK"

Преобразовать в нижний регистр:

('A'..'K').map &->(a){ a.downcase }
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]

В контексте определения метода, помещая амперсанд перед последним параметром, указывает, что метод может принимать блок и дает нам имя для ссылки на этот блок внутри тела метода.