2013-04-24 11 views
7

Wie im Ruby-Beispiel unten gezeigt, kann ich keine lambda mit falscher Anzahl von Argumenten wie Proc aus einer Method erstellt, da es streng ist, was die Anzahl der Argumente:So konvertieren Sie Methode oder Lambda in Nicht-Lambda-Prozess

# 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 

Wie erhalte ich eine Proc, die entweder von einem Proc kein Lambda ist das ist, oder von einem Method?

+0

Soweit ich sagen kann, können Sie eine Methode oder Lambda nicht in einen Nicht-Lambda-Prozess konvertieren. Was versuchst du zu erreichen? –

+0

@WallyAltman Die aufrufende Semantik eines Blocks, vor allem bezüglich der Anzahl der Argumente, aber es gibt noch einige andere Unterschiede. – michelpm

Antwort

2

Es gibt keine Möglichkeit, dies zu tun.

Neben dem Argument übergeben, frage ich mich, was Sie von einem return in der Methode erwarten würde. Es kann sich nur in lambda Weise verhalten ...

Wenn Sie wirklich dies tun müssen, müssen Sie Ihren eigenen Block, z.

Proc.new{ a } 

Für eine allgemeinere Art und Weise, werden Sie die arity des Verfahrens überprüfen und nur die erforderlichen Parameter übergeben.

+0

Ich stelle mir vor, dass es wegen 'return',' next' und 'break' unwahrscheinlich war, da ich als provisorische Maßnahme entweder Methoden mit splat geschrieben habe oder sie einen' Proc' zurückgegeben habe. Gibt es eine Möglichkeit zu beweisen, dass dies nicht möglich ist? – michelpm

+0

@michelpm: Kein Beweis, sorry. –

0

Versuchen Sie es in einer nicht-Lambda-Verpackung Proc, etwa so:

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

konvertieren Lambda zu Proc

Hier ist eine Behelfslösung, die eine lambda oder einen method Anruf in einem Proc und Anwendungen hüllt splat beliebige Anzahl von Argumenten zu handhaben:

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 

Dies würde immer funktionieren, egal wie viele Argumente übergeben wurden; Zusätzliche Argumente werden gelöscht und nil ersetzt die fehlenden Argumente.


Beispiel:

# 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!" 

Hinweis: Es gibt keine direkte Möglichkeit, einen Lambda oder einen Methodenaufruf zu einem proc zu konvertieren. Dies ist nur eine Problemumgehung und offensichtlich langsamer als der echte Deal (wegen Umbruch eines Anrufs in einem anderen).

Verwandte Themen