2013-04-24 19 views
7

Jak pokazano w poniższym przykładzie ruby, nie mogę wywołać lambda z nieprawidłową liczbą argumentów jako Proc utworzoną z Method, ponieważ jest ona ścisła w odniesieniu do liczby argumentów:Jak przekonwertować metodę lub lambda na procę inną niż lambda

# 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 

Jak mogę dostać Proc który nie jest lambda albo z Proc czyli albo z Method?

+0

O ile mogę powiedzieć, nie można przekonwertować metody lub lambda na proc non-lambda. Co próbujesz osiągnąć? –

+0

@WallyAltman Wywołanie semantyki bloku, przede wszystkim w odniesieniu do liczby argumentów, ale istnieje kilka innych różnic. – michelpm

Odpowiedz

2

Nie ma sposobu, aby to zrobić.

Poza argumentem przemawiającym, zastanawiam się, czego można się spodziewać po metodzie return. Może zachowywać się tylko w sposób lambda ...

Jeśli naprawdę musisz to zrobić, musisz zbudować własny blok, np.

Proc.new{ a } 

na bardziej ogólny sposób, będziesz musiał sprawdzić arity metody i przekazać tylko wymagane parametry.

+0

Wyobrażam sobie, że było to mało prawdopodobne z powodu 'return',' next' i 'break', jako tymczasowej miary albo pisałem metody z ikoną, albo zwracałem je' Proc'. Czy istnieje sposób na potwierdzenie, że nie można tego zrobić? – michelpm

+0

@michelpm: Brak dowodów, przepraszam. –

0

Spróbuj owijając go w nie-lambda Proc, tak:

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

Konwersja Lambda do Proc

Oto obejście, które owija lambda lub method połączenia w Proc i zastosowań ikona obsługuje dowolną liczbę argumentów:

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 

To zawsze działa bez względu na liczbę przekazanych argumentów; Dodatkowe argumenty zostaną usunięte, a nil zastąpi brakujące argumenty.


przykład:

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

Uwaga: Nie ma bezpośredni sposób konwersji lambda lub połączenie metody do proc. Jest to tylko obejście i oczywiście wolniejsze niż prawdziwa umowa (z powodu zawijania jednego połączenia w drugim).