2013-04-24 61 views
7

如下面的ruby示例所示,我不能調用lambda參數的數量錯誤ProcMethod創建,因爲它嚴格限制參數的數量:如何將方法或lambda轉換爲非lambda proc

# method with no args 
def a; end 

instance_eval(&method(:a)) 
# ArgumentError: wrong number of arguments (1 for 0) 

method(:a).to_proc.call(1, 2, 3) 
# ArgumentError: wrong number of arguments (3 for 0) 

method(:a).to_proc.lambda? 
# => true 

我如何獲得一個Proc,是不是無論是從Proc一個lambda是或從Method

+0

據我所知,您不能將方法或lambda轉換爲非lambda proc。你想達到什麼目的? – 2013-04-24 17:51:36

+0

@WallyAltman塊的調用語義,首先是關於參數的數量,但還有其他幾個不同之處。 – michelpm 2013-04-24 17:58:06

回答

2

沒有辦法做到這一點。

除了參數傳遞之外,我還想知道在方法中您期望從return得到什麼。它只能以lambda的方式運行......

如果你真的需要這樣做,你需要建立自己的區塊,例如:

Proc.new{ a } 

對於一個更通用的方法,你必須檢查方法的arity,只有通過必要的參數。

+0

我想這不太可能是因爲'return','next'和'break',作爲一種臨時措施,我一直在用splat編寫方法或使它們返回一個'Proc'。有沒有辦法證明它不能完成? – michelpm 2013-04-25 19:03:54

+0

@michelpm:沒有證據,對不起。 – 2013-04-25 20:45:16

0

嘗試在非拉姆達Proc包裹它,就像這樣:

l = lambda {|a,b| puts "a: #{a}, b: #{b}" } 
p = proc {|a,b| l.call(a,b) } 

l.lambda? 
#=> true 
l.arity 
#=> 2 
l.call("hai") 
#=> ArgumentError: wrong number of arguments (1 for 2) 
l.call("hai", "bai", "weee", "womp", "woo") 
#=> ArgumentError: wrong number of arguments (5 for 2) 

p.lambda? 
#=> false 
p.arity 
#=> 2 
p.call("hai") 
#=> a: hai, b: 
p.call("hai", "bai", "weee", "womp", "woo") 
#=> a: hai, b: bai 
0

轉換LambdaProc

這裏有一個解決一個封裝了lambdamethod中的呼叫Proc和用途圖示以處理任意數量的參數:

def lambda_to_proc(lambda) 
    Proc.new do |*args| 
    diff = lambda.arity - args.size 
    diff = 0 if diff.negative? 
    args = args.concat(Array.new(diff, nil)).take(lambda.arity) 

    lambda.call(*args) 
    end 
end 

無論傳遞的參數數量如何,這都將始終有效;額外的參數將被丟棄,並且nil將替換缺失的參數。


例子:

# lambda with two args 
some_lambda = -> (a,b) { [a, b] } 

# method with no args 
def some_method; "hello!"; end 

lambda_to_proc(some_lambda).call(5) 
# => [5, nil] 

lambda_to_proc(method(:some_method)).call(1,2,3) 
# => "hello!" 

注:有轉換一個lambda或方法調用一個進程沒有直接的方法。這只是一種解決方法,明顯比實際交易慢(因爲將一個呼叫包裝在另一個呼叫中)。