Una diferencia está en la forma en que manejan los argumentos. Crear un proceso usando proc {}y Proc.new {}son equivalentes. Sin embargo, el uso lambda {}le proporciona un proceso que verifica el número de argumentos que se le pasan. De ri Kernel#lambda:
Equivalente a Proc.new , excepto que los objetos Proc resultantes verifican el número de parámetros pasados cuando se llama.
Un ejemplo:
p =Proc.new {|a, b| puts a**2+b**2}# => #<Proc:0x3c7d28@(irb):1>
p.call 1,2# => 5
p.call 1# => NoMethodError: undefined method `**' for nil:NilClass
p.call 1,2,3# => 5
l = lambda {|a, b| puts a**2+b**2}# => #<Proc:0x15016c@(irb):5 (lambda)>
l.call 1,2# => 5
l.call 1# => ArgumentError: wrong number of arguments (1 for 2)
l.call 1,2,3# => ArgumentError: wrong number of arguments (3 for 2)
Además, como señala Ken, usar returndentro de un lambda devuelve el valor de ese lambda, pero usarlo returnen un proceso regresa del bloque que lo encierra.
Por lo tanto, para la mayoría de los usos rápidos son los mismos, pero si desea la comprobación automática de argumentos estrictos (que a veces también puede ayudar con la depuración), o si necesita usar la returndeclaración para devolver el valor del proceso, use lambda.
¿Sería exacto decir que las lambdas son muy parecidas a los métodos (comprobar los argumentos y volverá a partir de ellos) mientras que los procs son muy parecidos a los bloques (los argumentos no se verifican y una devolución volverá del método que contiene o lambda)?
pedz
He estado en Dios sabe cuántos sitios web y artículos ahora y nadie parece hablar sobre la utilidad de Procs vs. métodos vs. lambdas. Cada explicación solo proporciona un detalle desgarrador de cómo los valores de retorno, etc., son diferentes, pero ninguno sobre por qué es importante. Por ahora tengo que concluir que este es un desastre de diseño en Ruby.
ankush981
76
La verdadera diferencia entre procs y lambdas tiene mucho que ver con las palabras clave de control de flujo. Estoy hablando de return, raise, break, redo, retryetc. - esas palabras de control. Digamos que tiene una declaración de devolución en un proceso. Cuando llame a su proceso, no solo lo eliminará, sino que también regresará del método de cierre, por ejemplo:
El final putsen el método nunca se ejecutó, ya que cuando llamamos a nuestro proceso, returnsu contenido nos arrojó fuera del método. Sin embargo, si convertimos nuestro proceso a una lambda, obtenemos lo siguiente:
def my_method
puts "before proc"
my_proc = lambda do
puts "inside proc"returnend
my_proc.call
puts "after proc"end
my_method
shoaib@shoaib-ubuntu-vm:~/tmp$ ruby a.rb
before proc
inside proc
after proc
El retorno dentro de la lambda solo nos elimina de la propia lambda y el método de cierre continúa ejecutándose. La forma en que las palabras clave de flujo de control se tratan dentro de los procesos y lambdas es la principal diferencia entre ellas.
Primero, a lambdaverifica el número de argumentos que se le pasan, mientras procque a no. Esto significa que a lambdaarrojará un error si le pasa el número incorrecto de argumentos, mientras procque a ignorará los argumentos inesperados y los asignará nila los que faltan.
Segundo, cuando a lambdaregresa, devuelve el control al método de llamada; cuando a procregresa, lo hace de inmediato, sin volver al método de llamada.
Para ver cómo funciona esto, eche un vistazo al código a continuación. Nuestro primer método llama a proc; el segundo llama a lambda.
def batman_ironman_proc
victor =Proc.new {return"Batman will win!"}
victor.call
"Iron Man will win!"end
puts batman_ironman_proc # prints "Batman will win!"def batman_ironman_lambda
victor = lambda {return"Batman will win!"}
victor.call
"Iron Man will win!"end
puts batman_ironman_lambda # prints "Iron Man will win!"
Vea cómo procdice "¡Batman ganará!", Esto se debe a que vuelve inmediatamente, sin volver al método batman_ironman_proc.
Nuestro lambda, sin embargo, vuelve al método después de ser llamado, por lo que el método devuelve el último código que evalúa: "¡Iron Man ganará!"
1. Lambdas verifica el número de argumentos, mientras que los procs no
lam = lambda {|x| puts x }# creates a lambda that takes 1 argument
lam.call(2)# prints out 2
lam.call # ArgumentError: wrong number of arguments (0 for 1)
lam.call(1,2,3)# ArgumentError: wrong number of arguments (3 for 1)
En contraste, a los procesadores no les importa si se les pasa el número incorrecto de argumentos.
proc =Proc.new {|x| puts x }# creates a proc that takes 1 argument
proc.call(2)# prints out 2
proc.call # returns nil
proc.call(1,2,3)# prints out 1 and forgets about the extra arguments
2. Lambdas y procs tratan la palabra clave 'return' de manera diferente
'return' dentro de un lambda activa el código justo fuera del código lambda
Y para responder a su otra consulta, ¿cuál usar y cuándo? Seguiré a @jtbandes como él ha mencionado
Por lo tanto, para la mayoría de los usos rápidos son los mismos, pero si desea una verificación automática de argumentos estrictos (que a veces también puede ayudar con la depuración), o si necesita usar la instrucción return para devolver el valor del proceso, use lambda.
En términos generales, las lambdas son más intuitivas que los procesos porque son más similares a los métodos. Son bastante estrictos acerca de arity, y simplemente salen cuando llamas a return. Por esta razón, muchos Rubyists usan lambdas como primera opción, a menos que necesiten las características específicas de los procs.
Procs: Objetos de clase Proc. Al igual que los bloques, se evalúan en el ámbito donde se definen.
Lambdas también objetos de clase Procpero sutilmente diferentes de los procesos normales. Son cierres como bloques y procesos, y como tales se evalúan en el ámbito donde se definen.
a = proc { |x| x 2 }es lo mismo quea = Proc.new { |x| x 2 }
lacostenycoder
1
Aquí hay otra forma de entender esto.
Un bloque es un fragmento de código adjunto a la invocación a una llamada de un método en un objeto. En el ejemplo a continuación, self es una instancia de una clase anónima que hereda de ActionView :: Base en el marco de Rails (que a su vez incluye muchos módulos auxiliares). La tarjeta es un método que llamamos a uno mismo. Pasamos un argumento al método y luego adjuntamos siempre el bloque al final de la invocación del método:
self.card :contacts do|c|// a chunk of valid ruby code
end
Ok, entonces estamos pasando una porción de código a un método. Pero, ¿cómo hacemos uso de este bloque? Una opción es convertir el fragmento de código en un objeto. Ruby ofrece tres formas de convertir un fragmento de código en un objeto
# lambda> l = lambda {|a| a +1}> l.call(1)=>2# Proc.new> l2=Proc.new {|a| a +1}> l2.call(1)=>2# & as the last method argument with a local variable namedef add(&block)end
En el método anterior, el & convierte el bloque pasado al método en un objeto y almacena ese objeto en el bloque de variable local. De hecho, podemos mostrar que tiene el mismo comportamiento que lambda y Proc.new:
def add(&block)
block
end
l3 = add {|a| a +1}
l3.call(1)=>2
Esto es importante. Cuando pasa un bloque a un método y lo convierte usando &, el objeto que crea usa Proc.new para realizar la conversión.
Tenga en cuenta que evité el uso de "proc" como una opción. Eso es porque es Ruby 1.8, es lo mismo que lambda y en Ruby 1.9, es lo mismo que Proc.new y en todas las versiones de Ruby se debe evitar.
Entonces, ¿cuál es la diferencia entre lambda y Proc.new?
Primero, en términos de paso de parámetros, lambda se comporta como una llamada a un método. Planteará una excepción si pasa el número incorrecto de argumentos. Por el contrario, Proc.new se comporta como una asignación paralela. Todos los argumentos no utilizados se convierten en nulo:
> l = lambda {|a,b| puts "#{a} + #{b}"}=>#<Proc:0x007fbffcb47e40@(irb):19 (lambda)> > l.call(1)ArgumentError: wrong number of arguments (1for2)> l2 =Proc.new {|a,b| puts "#{a} + #{b}"}=>#<Proc:0x007fbffcb261a0@(irb):21> > l2.call(1)1+
En segundo lugar, lambda y Proc.new manejan la palabra clave return de manera diferente. Cuando realiza un retorno dentro de Proc.new, en realidad regresa del método de inclusión, es decir, el contexto circundante. Cuando regresa de un bloque lambda, simplemente regresa del bloque, no del método de cierre. Básicamente, sale de la llamada al bloque y continúa la ejecución con el resto del método de cierre.
>def add(a,b)
l =Proc.new {return a + b}
l.call
puts "now exiting method"end> add(1,1)=>2# NOTICE it never prints the message "now exiting method">def add(a,b)
l = lambda {return a + b }
l.call
puts "now exiting method"end> add(1,1)=> now exiting method # NOTICE this time it prints the message "now exiting method"
Entonces, ¿por qué esta diferencia de comportamiento? La razón es porque con Proc.new, podemos usar iteradores dentro del contexto de los métodos de cierre y sacar conclusiones lógicas. Mira este ejemplo:
>def print(max)[1,2,3,4,5].each do|val|
puts val
returnif val > max
endend> print(3)1234
Esperamos que cuando invoquemos return dentro del iterador, regrese del método de cierre. Recuerde que los bloques pasados a los iteradores se convierten en objetos usando Proc.new y es por eso que cuando usamos return, saldrá del método de cierre.
Puede pensar en lambdas como métodos anónimos, que aíslan bloques de código individuales en un objeto que se puede tratar como un método. En última instancia, piense que una lambda se comporta como un método anónimo y que Proc.new se comporta como un código en línea.
La diferencia entre proc y lambda es que proc es solo una copia de código con argumentos reemplazados a su vez, mientras que lambda es una función como en otros lenguajes. (comportamiento de devolución, verificación de argumentos)
return
declaración devuelve enproc
versuslambda
.Respuestas:
Una diferencia está en la forma en que manejan los argumentos. Crear un proceso usando
proc {}
yProc.new {}
son equivalentes. Sin embargo, el usolambda {}
le proporciona un proceso que verifica el número de argumentos que se le pasan. Deri Kernel#lambda
:Un ejemplo:
Además, como señala Ken, usar
return
dentro de un lambda devuelve el valor de ese lambda, pero usarloreturn
en un proceso regresa del bloque que lo encierra.Por lo tanto, para la mayoría de los usos rápidos son los mismos, pero si desea la comprobación automática de argumentos estrictos (que a veces también puede ayudar con la depuración), o si necesita usar la
return
declaración para devolver el valor del proceso, uselambda
.fuente
La verdadera diferencia entre procs y lambdas tiene mucho que ver con las palabras clave de control de flujo. Estoy hablando de
return
,raise
,break
,redo
,retry
etc. - esas palabras de control. Digamos que tiene una declaración de devolución en un proceso. Cuando llame a su proceso, no solo lo eliminará, sino que también regresará del método de cierre, por ejemplo:El final
puts
en el método nunca se ejecutó, ya que cuando llamamos a nuestro proceso,return
su contenido nos arrojó fuera del método. Sin embargo, si convertimos nuestro proceso a una lambda, obtenemos lo siguiente:El retorno dentro de la lambda solo nos elimina de la propia lambda y el método de cierre continúa ejecutándose. La forma en que las palabras clave de flujo de control se tratan dentro de los procesos y lambdas es la principal diferencia entre ellas.
fuente
Solo hay dos diferencias principales.
lambda
verifica el número de argumentos que se le pasan, mientrasproc
que a no. Esto significa que alambda
arrojará un error si le pasa el número incorrecto de argumentos, mientrasproc
que a ignorará los argumentos inesperados y los asignaránil
a los que faltan.lambda
regresa, devuelve el control al método de llamada; cuando aproc
regresa, lo hace de inmediato, sin volver al método de llamada.Para ver cómo funciona esto, eche un vistazo al código a continuación. Nuestro primer método llama a
proc
; el segundo llama alambda
.Vea cómo
proc
dice "¡Batman ganará!", Esto se debe a que vuelve inmediatamente, sin volver al método batman_ironman_proc.Nuestro
lambda
, sin embargo, vuelve al método después de ser llamado, por lo que el método devuelve el último código que evalúa: "¡Iron Man ganará!"fuente
# Ejemplos de procesos
# Ejemplos Lambda
Diferencias entre Procs y Lambdas
Antes de entrar en las diferencias entre procs y lambdas, es importante mencionar que ambos son objetos Proc.
Sin embargo, las lambdas son un 'sabor' diferente de los procs. Esta ligera diferencia se muestra al devolver los objetos.
1. Lambdas verifica el número de argumentos, mientras que los procs no
En contraste, a los procesadores no les importa si se les pasa el número incorrecto de argumentos.
2. Lambdas y procs tratan la palabra clave 'return' de manera diferente
'return' dentro de un lambda activa el código justo fuera del código lambda
'return' dentro de un proceso activa el código fuera del método donde se ejecuta el proceso
Y para responder a su otra consulta, ¿cuál usar y cuándo? Seguiré a @jtbandes como él ha mencionado
Publicado originalmente aquí
fuente
En términos generales, las lambdas son más intuitivas que los procesos porque son más similares a los métodos. Son bastante estrictos acerca de arity, y simplemente salen cuando llamas a return. Por esta razón, muchos Rubyists usan lambdas como primera opción, a menos que necesiten las características específicas de los procs.
Procs: Objetos de clase
Proc
. Al igual que los bloques, se evalúan en el ámbito donde se definen. Lambdas también objetos de claseProc
pero sutilmente diferentes de los procesos normales. Son cierres como bloques y procesos, y como tales se evalúan en el ámbito donde se definen.Creando Proc
Creando lambda
b = lambda { |x| x 2
}fuente
a = proc { |x| x 2 }
es lo mismo quea = Proc.new { |x| x 2 }
Aquí hay otra forma de entender esto.
Un bloque es un fragmento de código adjunto a la invocación a una llamada de un método en un objeto. En el ejemplo a continuación, self es una instancia de una clase anónima que hereda de ActionView :: Base en el marco de Rails (que a su vez incluye muchos módulos auxiliares). La tarjeta es un método que llamamos a uno mismo. Pasamos un argumento al método y luego adjuntamos siempre el bloque al final de la invocación del método:
Ok, entonces estamos pasando una porción de código a un método. Pero, ¿cómo hacemos uso de este bloque? Una opción es convertir el fragmento de código en un objeto. Ruby ofrece tres formas de convertir un fragmento de código en un objeto
En el método anterior, el & convierte el bloque pasado al método en un objeto y almacena ese objeto en el bloque de variable local. De hecho, podemos mostrar que tiene el mismo comportamiento que lambda y Proc.new:
Esto es importante. Cuando pasa un bloque a un método y lo convierte usando &, el objeto que crea usa Proc.new para realizar la conversión.
Tenga en cuenta que evité el uso de "proc" como una opción. Eso es porque es Ruby 1.8, es lo mismo que lambda y en Ruby 1.9, es lo mismo que Proc.new y en todas las versiones de Ruby se debe evitar.
Entonces, ¿cuál es la diferencia entre lambda y Proc.new?
Primero, en términos de paso de parámetros, lambda se comporta como una llamada a un método. Planteará una excepción si pasa el número incorrecto de argumentos. Por el contrario, Proc.new se comporta como una asignación paralela. Todos los argumentos no utilizados se convierten en nulo:
En segundo lugar, lambda y Proc.new manejan la palabra clave return de manera diferente. Cuando realiza un retorno dentro de Proc.new, en realidad regresa del método de inclusión, es decir, el contexto circundante. Cuando regresa de un bloque lambda, simplemente regresa del bloque, no del método de cierre. Básicamente, sale de la llamada al bloque y continúa la ejecución con el resto del método de cierre.
Entonces, ¿por qué esta diferencia de comportamiento? La razón es porque con Proc.new, podemos usar iteradores dentro del contexto de los métodos de cierre y sacar conclusiones lógicas. Mira este ejemplo:
Esperamos que cuando invoquemos return dentro del iterador, regrese del método de cierre. Recuerde que los bloques pasados a los iteradores se convierten en objetos usando Proc.new y es por eso que cuando usamos return, saldrá del método de cierre.
Puede pensar en lambdas como métodos anónimos, que aíslan bloques de código individuales en un objeto que se puede tratar como un método. En última instancia, piense que una lambda se comporta como un método anónimo y que Proc.new se comporta como un código en línea.
fuente
Una publicación útil sobre guías de rubí: bloques, procs y lambdas
fuente
La diferencia entre proc y lambda es que proc es solo una copia de código con argumentos reemplazados a su vez, mientras que lambda es una función como en otros lenguajes. (comportamiento de devolución, verificación de argumentos)
fuente