ndn - 1 year ago 36

Ruby Question

I want to convert a proc that exhibits lambda behavior (argument checking) into one that doesn't. The following is a very contrived example, but it should get the point across:

The aim is to create a DSL that looks something like this:

`NumberSeries.perform do`

add first_series: -> { natural_numbers.take(10) },

second_series: -> { fibonacci_numbers.take(10) }

end

Note that

`natural_numbers`

`fibonacci_numbers`

`add`

`NaturalNumbersFibonacciNumbers = Struct.new(:natural_numbers, :fibonacci_numbers)`

FAMOUS_NUMBER_SERIES = NaturalNumbersFibonacciNumbers.

new(natural_numbers, fibonacci_numbers)

def add(first_series:, second_series:)

first_numbers = FAMOUS_NUMBER_SERIES.instance_eval(&first_series)

second_numbers = FAMOUS_NUMBER_SERIES.instance_eval(&second_series)

first_numbers.zip(second_numbers).map { |x, y| x + y }

end

Now, if I replace

`->`

`proc`

ArgumentError: wrong number of arguments (1 for 0)

as

`BasicObject#instance_eval`

I don't want to use

`Fiddle`

Answer

`instance_exec`

is an alternative to `instance_eval`

that allows you to control the parameters passed to the block, and doesn’t pass the receiver as `instance_eval`

does. You can use it as a workaround to your problem as it allows you to pass zero args:

```
irb:108:0> Object.new.instance_eval &-> { puts "Hello" }
ArgumentError: wrong number of arguments (given 1, expected 0)
from (irb):108:in `block in irb_binding'
from (irb):108:in `instance_eval'
from (irb):108
from /Users/matt/.rubies/ruby-2.3.0/bin/irb:11:in `<main>'
irb:109:0> Object.new.instance_exec &-> { puts "Hello" }
Hello
=> nil
```

Source (Stackoverflow)