2010-02-09 13 views
17

funciona este código como se esperaba (no hace nada, incluso no produce advertencia/errores):Rubí argumentos lambda

l = lambda {|i|} 
l.call(1) 

Este código produce advertencia (advertencia: los valores múltiples de un parámetro de bloque (0 a 1)):

l = lambda {|i|} 
l.call 

Y este código falla con el error (ArgumentError: número incorrecto de argumentos (0 a 2)):

l = lambda {|i, y|} 
l.call 

iésimo debería ese lambda requiere que se pasen todos los argumentos.

Y del segundo ejemplo veo que no lo es. ¿Por qué funciona cuando solo se da un argumento y funciona como se espera (falla con error) con más de un argumento?

PS: rubí 1.8.6 (2008-08-11 Patchlevel 287) [universal darwin9.0]

ACTUALIZACIÓN: he comprobado estas muestras con el rubí 1.9.1p376. Y funciona como se esperaba: el segundo ejemplo también produce un error. Parece que esta es una característica de la versión 1.8 (o < = 1.8)

Respuesta

12

Las lambdas son raras así, su comportamiento es diferente cuando tienes menos de dos argumentos. Consulte this article para obtener más información.

12

This script le enseñará todo lo que necesita saber sobre los cierres en Ruby.

# So, what's the final verdict on those 7 closure-like entities?   
# 
#              "return" returns from closure 
#         True closure? or declaring context...?   Arity check? 
#         --------------- ----------------------------- ------------------- 
# 1. block (called with yield)  N    declaring      no 
# 2. block (&b => f(&b) => yield) N    declaring      no 
# 3. block (&b => b.call)   Y except return declaring      warn on too few 
# 4. Proc.new      Y except return declaring      warn on too few 
# 5. proc         <<< alias for lambda in 1.8, Proc.new in 1.9 >>> 
# 6. lambda       Y    closure       yes, except arity 1 
# 7. method       Y    closure       yes 
+0

Lo sentimos, pero no puedo encontrar una respuesta allí. ¿Podría señalar? –

+0

Agregó un puntero :) – Trevoke

+0

¡Gracias!Pero de todos modos, todavía no está claro por qué existe ese comportamiento (para ser correcto, existió) –

2

Cuando una lambda espera argumentos y nosotros no los proporcionamos, o proporcionamos el número de argumentos incorrecto, se lanza una excepción.

l = lambda { |name| puts "Today we will practice #{name} meditation." } 
l.call 
ArgumentError: wrong number of arguments (given 0, expected 1) 

Podemos utilizar el método aridad para averiguar el número de argumentos esperados:

l.arity # Output: => 1 

Al igual que métodos, lambdas aceptan todos los siguientes tipos de parámetros/argumentos:

  • Parámetros posicionales (obligatorios y opcionales)
  • Parámetro splat simple (*);
  • Parámetros de palabra clave (obligatorios y opcionales);
  • Parámetro doble splat (**);
  • Parámetro de bloque explícito prefijado con ampersand (&).

Los siguientes ejemplos ilustran la sintaxis de una lambda que toma varios tipos de argumentos.

# Stabby syntax 
l = -> (cushion, meditation="kinhin", *room_items, time:, posture: "kekkafuza", **periods, &p) do 
    p.call 
end 

# Regular syntax 
l = lambda do |cushion, meditation="kinhin", *room_items, time:, posture:  "kekkafuza", **periods, &p| 
    p.call 
end 

l.call("zafu", "zazen", "zabuton", "incense", time: 40, period1: "morning", period2: "afternoon") { puts "Hello from inside the block, which is now a proc." } 

Output: 
Hello from inside the block, which is now a proc. 

Lambdas manejan los argumentos de la misma manera que los métodos. Hay una explicación completa de todos los tipos de parámetro/argumento anteriores en this blog post about methods.