332 votos

Cuando el uso de lambda, cuando para utilizar Proc.new?

En Ruby 1.8, existen sutiles diferencias entre proc/lambda, por un lado, y Proc.new en el otro.

  • ¿Cuáles son esas diferencias?
  • Puede dar pautas sobre cómo decidir cuál elegir?
  • En Ruby 1.9, proc y lambda son diferentes. ¿Cuál es el trato?

378voto

Joey deVilla Puntos 4487

Otro importante pero sutil diferencia está en la forma de procs creado con lambda y procs creado con Proc.new de manejar la return declaración:

  • En un lambda-creado proc, la return instrucción devuelve sólo desde el proceso mismo de
  • En un Proc.new-creado proc, la return afirmación es un poco más sorprendente: se devuelve el control no sólo del proceso, sino también del método que encierra el proc!

Aquí lambda-creado proc s return en acción. Se comporta de una manera que probablemente esperar:

def whowouldwin

Ahora, aquí hay un
-creado proc s
haciendo la misma cosa. Estás a punto de ver uno de esos casos donde Ruby rompe el tan cacareado Principio de la menor Sorpresa:

  mylambda = lambda {return "Freddy"}

Gracias a este sorprendente comportamiento (así como escribir menos), que tienden a favorecer el uso de
sobre mylambda.call cuando la toma de procs.

95voto

Peter Wagenet Puntos 4069

Aclaraciones:

Joey dice que la devolución comportamiento de Proc.new es de extrañar. Sin embargo, cuando se considera que Proc.new se comporta como un bloque de esto no es de extrañar pues que es exactamente lo que los bloques de comportarse. lambas por otro lado se comportan más como métodos.

Esta realidad explica por qué los Procs son flexibles cuando se trata de arity (número de argumentos), mientras que las lambdas no lo son. Los bloques no requieren que todos sus argumentos para siempre, pero los métodos de hacer (a menos que un defecto). Mientras que la prestación de lambda argumento predeterminado no es una opción en Ruby 1.8, es ahora soportado en Ruby 1.9 con la alternativa de la sintaxis lambda (como lo señaló la webmat):

concat = ->(a, b=2){ "#{a}#{b}" }
concat.call(4,5) # => "45"
concat.call(1)   # => "12"

Y Michiel de Mare (OP) es incorrecta acerca de los Procedimientos y lambda comportan de la misma con arity en Ruby 1.9. He comprobado que aún mantienen el comportamiento de 1.8 como se especifica anteriormente.

break declaraciones realmente no tienen mucho sentido en cualquiera de los Procedimientos o las lambdas. En Procs, el salto de regreso de Proc.new que ya se ha completado. Y eso no tiene ningún sentido para romper de una expresión lambda, ya que es esencialmente un método, y que nunca rompería desde el nivel superior de un método.

next, redoy raise comportan de la misma, tanto en Procedimientos y funciones lambda. Mientras que retry no está permitido en ninguno de los dos y provocará una excepción.

Y por último, la proc método nunca debe ser usado como es inconsistente y tiene un comportamiento inesperado. En Ruby 1.8 realmente devuelve un lambda! En Ruby 1.9 esto ha sido un fijo y se devuelve un Proc. Si desea crear un Proc, con el palo Proc.new.

Para obtener más información, recomiendo O'Reilly es El Lenguaje de Programación Ruby , que es mi fuente de la mayor parte de esta información.

43voto

Mike Stone Puntos 21293

He encontrado esta página que muestra cuál es la diferencia entre Proc.new y lambda. Según la página, la única diferencia es que una expresión lambda es estricto sobre el número de argumentos que se acepta, mientras que Proc.new convierte los argumentos que faltan de nada. Aquí es un ejemplo de la IRB sesión ilustra la diferencia:

irb(main):001:0> > l = lambda { |x, y| x + y }
=> #<Proc:0x00007fc605ec0748@(irb):1>
irb(main):002:0> p = Proc.new { |x, y| x + y }
=> #<Proc:0x00007fc605ea8698@(irb):2>
irb(main):003:0> l.call "hola", "mundo"
=> "helloworld"
irb(main):004:0> tecla p.call "hola", "mundo"
=> "helloworld"
irb(main):005:0> l.call "hola"
ArgumentError: número incorrecto de argumentos (1 de 2)
 de investigación clínica (ceic):1
 de investigación clínica (ceic):5:en `call'
 de investigación clínica (ceic):5
 desde :0
irb(main):006:0> tecla p.call "hola"
TypeError: no se puede convertir nil en Cadena
 de investigación clínica (ceic):2:en el `+'
 de investigación clínica (ceic):2
 de investigación clínica (ceic):6:en `call'
 de investigación clínica (ceic):6
 desde :0

La página también se recomienda el uso de lambda, a menos que usted específicamente se desea que el error tolerante comportamiento. Estoy de acuerdo con este sentimiento. El uso de una expresión lambda que parece un poco más conciso, y con una insignificante diferencia, parece que la mejor opción en el promedio de la situación.

Como para Ruby 1.9, lo siento, no he mirado en 1.9, pero no me imagine que iba a cambiar mucho (no tome mi palabra para ella, aunque, parece que han oído hablar de algunos cambios, así que probablemente soy mal allí).

11voto

webmat Puntos 13359

No puedo decir mucho acerca de las diferencias sutiles. Sin embargo, puedo señalar que Ruby 1.9 permite ahora a los parámetros opcionales para las lambdas y bloques.

Aquí está la nueva sintaxis de la stabby lambdas bajo 1.9:

stabby = ->(msg='inside the stabby lambda') { puts msg }

Ruby 1.8 no tienen esa sintaxis. Tampoco la forma convencional de declarar bloques/lambdas de apoyo opcional args:

# under 1.8
l = lambda { |msg = 'inside the stabby lambda'|  puts msg }
SyntaxError: compile error
(irb):1: syntax error, unexpected '=', expecting tCOLON2 or '[' or '.'
l = lambda { |msg = 'inside the stabby lambda'|  puts msg }

Ruby 1.9, sin embargo, compatible con argumentos opcionales incluso con la antigua sintaxis:

l = lambda { |msg = 'inside the regular lambda'|  puts msg }
#=> #<Proc:0x0e5dbc@(irb):1 (lambda)>
l.call
#=> inside the regular lambda
l.call('jeez')
#=> jeez

Si quieres construir Ruby1.9 para Leopard o Linux, echa un vistazo a este artículo (shameless self promotion).

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X