2016-04-14 177 views
4

我想將展現lambda行爲(參數檢查)的proc轉換爲不具有lambda行爲的參數。下面是一個很做作的例子,但它應該得到跨越點:忽略lambda參數檢查

的目的是創造一個DSL看起來是這樣的:

NumberSeries.perform do 
    add first_series: -> { natural_numbers.take(10) }, 
     second_series: -> { fibonacci_numbers.take(10) } 
end 

注意natural_numbersfibonacci_numbers作爲參數不傳遞在DSL中。的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 

現在,如果我在DSL與proc取代->,它會工作。然而,保持lambda表達式,我會得到

ArgumentError: wrong number of arguments (1 for 0)

BasicObject#instance_eval產生自我拉姆達,但拉姆達預計沒有參數。


我不想使用Fiddle,原因很明顯。

+2

是否'instance_exec'工作,而不是 - 它允許你傳遞參數(或不在這種情況下)? – matt

+0

我很困惑。爲什麼不直接用procs定義DSL? 'add first_series:proc {natural_numbers.take(10)}'同樣優雅。 –

+0

@matt,yep,'instance_exec'完成了這個訣竅。不知道我怎麼沒有想到這一點。儘管它沒有回答這個問題,但它解決了原來的問題,所以補充說,作爲答案,如果沒有人知道如何去做,我會接受它。 – ndn

回答

1

instance_execinstance_eval的替代方案,它允許您控制傳遞給該塊的參數,並且不會像instance_eval那樣通過接收器。你可以使用它作爲你的問題的解決方法,因爲它允許你通過零參數:

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