Block lambda transfer

I am trying to define a block that I will use to pass each method from several ranges. Instead of overriding a block in each range, I would like to create a lamba and pass the lambda as such:

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

However, I get the following error:

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

Any ideas what is going on here?

+48
ruby lambda
Nov 17 2018-11-11T00:
source share
2 answers

Note the ampersand ( & ) in the argument, for example:

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

This means that you pass it as a special parameter to the method block. Otherwise, it is interpreted as a normal argument.

It also reflects their way of capturing and accessing the block parameter inside the method itself:

 # 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 
+62
Nov 17 2018-11-11T00:
source share
— -

The trick is to use & , which tells Ruby to convert this argument to Proc , if necessary, and then use this object as a block of methods. Starting with Ruby 1.9 there is a shortcut for lambda (anonymous) functions. So you can write the code as follows:

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

will take each element of the array and calculate its power

this is the same as this code:

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

for Ruby 1.8:

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

To solve your problem, you can use the Array reduce method ( 0 is the initial value):

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

Passing a lambda function to reduce bit complicated, but the anonymous block is almost the same as the lambda.

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

Or you can write lines like this:

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

Convert to lowercase:

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

In the context of a method definition, placing an ampersand in front of the last parameter indicates that the method can take a block and gives us a name to refer to this block inside the method body.

+11
Mar 21 '14 at 21:55
source share



All Articles