Uma diferença está na maneira como eles lidam com argumentos. Criando um proc usando proc {}e Proc.new {}é equivalente. No entanto, usar lambda {}fornece um processo que verifica o número de argumentos passados para ele. De ri Kernel#lambda:
Equivalente a Proc.new , exceto os objetos Proc resultantes, verifica o número de parâmetros passados quando chamados.
Um exemplo:
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)
Além disso, como Ken aponta, usar returndentro de um lambda retorna o valor desse lambda, mas usar returnem proc proc retorna do bloco anexo.
Portanto, para os usos mais rápidos, eles são os mesmos, mas se você desejar a verificação automática de argumentos estritos (que às vezes também pode ajudar na depuração), ou se precisar usar a returninstrução para retornar o valor do proc, use lambda.
Seria correto dizer que lambdas são muito parecidos com métodos (argumentos de verificação e retorno retornará deles) enquanto procs são muito parecidos com blocos (argumentos não são verificados e um retorno retornará do método ou lambda)?
pedz
Estive em Deus sabe quantos sites e artigos até agora e ninguém parece falar sobre a utilidade do Procs vs. métodos vs. lambdas. Toda explicação fornece apenas um detalhe impressionante de como os valores de retorno etc. são diferentes, mas nenhum sobre o motivo. Por enquanto, devo concluir que essa é uma bagunça no design do Ruby.
ankush981 6/04
76
A diferença real entre procs e lambdas tem tudo a ver com palavras-chave de fluxo de controle. Estou a falar de return, raise, break, redo, retryetc. - essas palavras de controle. Digamos que você tenha uma declaração de retorno em um proc. Quando você chama seu proc, ele não apenas o despeja, mas também retorna do método anexo, por exemplo:
A final putsdo método nunca foi executada, pois quando chamamos nosso proc, a parte returninterna dele nos expulsou do método. Se, no entanto, convertermos nosso proc em um lambda, obteremos o seguinte:
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
O retorno dentro do lambda apenas nos despeja do próprio lambda e o método envolvente continua em execução. A maneira como as palavras-chave do fluxo de controle são tratadas nos procs e lambdas é a principal diferença entre elas
Primeiro, a lambdaverifica o número de argumentos passados, enquanto a procnão. Isso significa que a lambdagerará um erro se você passar o número errado de argumentos, enquanto a procignorará argumentos inesperados e os atribuirá nila qualquer um que estiver faltando.
Segundo, quando lambdaretorna, ele passa o controle de volta ao método de chamada; quando procretorna, o faz imediatamente, sem voltar ao método de chamada.
Para ver como isso funciona, dê uma olhada no código abaixo. Nosso primeiro método chama a proc; a segunda chama 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!"
Veja como procdiz "Batman vai vencer!", Isso ocorre porque ele retorna imediatamente, sem voltar ao método batman_ironman_proc.
lambdaNo entanto, nosso método retorna ao método após ser chamado, portanto, o método retorna o último código que avalia: "O Homem de Ferro vencerá!"
1. Lambdas verifica o número de argumentos, enquanto procs não
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)
Por outro lado, os procs não se importam se recebem o número errado 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 e procs tratam a palavra-chave 'return' de maneira diferente
'return' dentro de um lambda aciona o código fora do código lambda
E para responder sua outra pergunta, qual usar e quando? Vou seguir @jtbandes como ele mencionou
Portanto, para os usos mais rápidos, eles são os mesmos, mas se você desejar a verificação automática de argumentos estritos (que às vezes também pode ajudar na depuração), ou se precisar usar a instrução de retorno para retornar o valor do proc, use lambda.
De um modo geral, as lambdas são mais intuitivas que os procs porque são mais semelhantes aos métodos. Eles são bastante rígidos quanto à aridade e simplesmente saem quando você chama de retorno. Por esse motivo, muitos rubiistas usam lambdas como primeira opção, a menos que precisem dos recursos específicos de procs.
Procs: Objetos de classe Proc. Como blocos, eles são avaliados no escopo em que são definidos.
Lambdas: também objetos de classe, Procmas sutilmente diferentes dos procs regulares. São fechamentos como blocos e procs e, como tal, são avaliados no escopo em que são definidos.
a = proc { |x| x 2 }é o mesmo quea = Proc.new { |x| x 2 }
lacostenycoder
1
Aqui está outra maneira de entender isso.
Um bloco é um pedaço de código anexado à chamada para uma chamada de um método em um objeto. No exemplo abaixo, self é uma instância de uma classe anônima herdada de ActionView :: Base na estrutura do Rails (que inclui muitos módulos auxiliares). cartão é um método que chamamos de auto. Passamos um argumento para o método e sempre anexamos o bloco ao final da invocação do método:
self.card :contacts do|c|// a chunk of valid ruby code
end
Ok, estamos passando um pedaço de código para um método. Mas como usamos esse bloco? Uma opção é converter o pedaço de código em um objeto. Ruby oferece três maneiras de converter um pedaço de código em um 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
No método acima, o & converte o bloco passado para o método em um objeto e armazena esse objeto no bloco variável local. De fato, podemos mostrar que ele tem o mesmo comportamento que o lambda e o Proc.new:
def add(&block)
block
end
l3 = add {|a| a +1}
l3.call(1)=>2
Isso é importante. Quando você passa um bloco para um método e o converte usando &, o objeto que ele cria usa Proc.new para fazer a conversão.
Observe que eu evitei o uso de "proc" como uma opção. Isso porque Ruby 1.8, é o mesmo que lambda e no Ruby 1.9, é o mesmo que Proc.new e em todas as versões do Ruby deve ser evitado.
Então você pergunta qual é a diferença entre lambda e Proc.new?
Primeiro, em termos de passagem de parâmetro, o lambda se comporta como uma chamada de método. Irá gerar uma exceção se você passar o número errado de argumentos. Por outro lado, o Proc.new se comporta como atribuição paralela. Todos os argumentos não utilizados são convertidos em zero:
> 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+
Segundo, lambda e Proc.new tratam a palavra-chave return de maneira diferente. Quando você faz um retorno dentro do Proc.new, ele realmente retorna do método anexo, ou seja, do contexto circundante. Quando você retorna de um bloco lambda, ele apenas retorna do bloco, não do método envolvente. Basicamente, ele sai da chamada para o bloco e continua a execução com o restante do método anexo.
>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"
Então, por que essa diferença comportamental? O motivo é que, com o Proc.new, podemos usar iteradores dentro do contexto de métodos anexos e tirar conclusões lógicas. Veja este exemplo:
>def print(max)[1,2,3,4,5].each do|val|
puts val
returnif val > max
endend> print(3)1234
Esperamos que, quando invocarmos o retorno dentro do iterador, ele retornará do método envolvente. Lembre-se de que os blocos passados para os iteradores são convertidos em objetos usando Proc.new e é por isso que quando usamos return, ele sai do método envolvente.
Você pode pensar em lambdas como métodos anônimos, eles isolam blocos individuais de código em um objeto que pode ser tratado como um método. Por fim, pense em um lambda se comportando como um método anômalo e Proc.novo se comportando como código embutido.
as diferenças entre proc e lambda é que proc é apenas uma cópia do código com argumentos substituídos por sua vez, enquanto lambda é uma função como em outros idiomas. (comportamento de retorno, verificações de argumentos)
return
retorno da declaração emproc
versuslambda
.Respostas:
Uma diferença está na maneira como eles lidam com argumentos. Criando um proc usando
proc {}
eProc.new {}
é equivalente. No entanto, usarlambda {}
fornece um processo que verifica o número de argumentos passados para ele. Deri Kernel#lambda
:Um exemplo:
Além disso, como Ken aponta, usar
return
dentro de um lambda retorna o valor desse lambda, mas usarreturn
em proc proc retorna do bloco anexo.Portanto, para os usos mais rápidos, eles são os mesmos, mas se você desejar a verificação automática de argumentos estritos (que às vezes também pode ajudar na depuração), ou se precisar usar a
return
instrução para retornar o valor do proc, uselambda
.fonte
A diferença real entre procs e lambdas tem tudo a ver com palavras-chave de fluxo de controle. Estou a falar de
return
,raise
,break
,redo
,retry
etc. - essas palavras de controle. Digamos que você tenha uma declaração de retorno em um proc. Quando você chama seu proc, ele não apenas o despeja, mas também retorna do método anexo, por exemplo:A final
puts
do método nunca foi executada, pois quando chamamos nosso proc, a partereturn
interna dele nos expulsou do método. Se, no entanto, convertermos nosso proc em um lambda, obteremos o seguinte:O retorno dentro do lambda apenas nos despeja do próprio lambda e o método envolvente continua em execução. A maneira como as palavras-chave do fluxo de controle são tratadas nos procs e lambdas é a principal diferença entre elas
fonte
Existem apenas duas diferenças principais.
lambda
verifica o número de argumentos passados, enquanto aproc
não. Isso significa que alambda
gerará um erro se você passar o número errado de argumentos, enquanto aproc
ignorará argumentos inesperados e os atribuiránil
a qualquer um que estiver faltando.lambda
retorna, ele passa o controle de volta ao método de chamada; quandoproc
retorna, o faz imediatamente, sem voltar ao método de chamada.Para ver como isso funciona, dê uma olhada no código abaixo. Nosso primeiro método chama a
proc
; a segunda chama alambda
.Veja como
proc
diz "Batman vai vencer!", Isso ocorre porque ele retorna imediatamente, sem voltar ao método batman_ironman_proc.lambda
No entanto, nosso método retorna ao método após ser chamado, portanto, o método retorna o último código que avalia: "O Homem de Ferro vencerá!"fonte
# Proc Exemplos
# Lambda Examples
Diferenças entre Procs e Lambdas
Antes de abordar as diferenças entre procs e lambdas, é importante mencionar que ambos são objetos Proc.
No entanto, lambdas são um 'sabor' diferente de procs. Essa pequena diferença é mostrada ao retornar os objetos.
1. Lambdas verifica o número de argumentos, enquanto procs não
Por outro lado, os procs não se importam se recebem o número errado de argumentos.
2. Lambdas e procs tratam a palavra-chave 'return' de maneira diferente
'return' dentro de um lambda aciona o código fora do código lambda
'return' dentro de um proc aciona o código fora do método em que o proc está sendo executado
E para responder sua outra pergunta, qual usar e quando? Vou seguir @jtbandes como ele mencionou
Originalmente publicado aqui
fonte
De um modo geral, as lambdas são mais intuitivas que os procs porque são mais semelhantes aos métodos. Eles são bastante rígidos quanto à aridade e simplesmente saem quando você chama de retorno. Por esse motivo, muitos rubiistas usam lambdas como primeira opção, a menos que precisem dos recursos específicos de procs.
Procs: Objetos de classe
Proc
. Como blocos, eles são avaliados no escopo em que são definidos. Lambdas: também objetos de classe,Proc
mas sutilmente diferentes dos procs regulares. São fechamentos como blocos e procs e, como tal, são avaliados no escopo em que são definidos.Criando Proc
Criando lambda
b = lambda { |x| x 2
}fonte
a = proc { |x| x 2 }
é o mesmo quea = Proc.new { |x| x 2 }
Aqui está outra maneira de entender isso.
Um bloco é um pedaço de código anexado à chamada para uma chamada de um método em um objeto. No exemplo abaixo, self é uma instância de uma classe anônima herdada de ActionView :: Base na estrutura do Rails (que inclui muitos módulos auxiliares). cartão é um método que chamamos de auto. Passamos um argumento para o método e sempre anexamos o bloco ao final da invocação do método:
Ok, estamos passando um pedaço de código para um método. Mas como usamos esse bloco? Uma opção é converter o pedaço de código em um objeto. Ruby oferece três maneiras de converter um pedaço de código em um objeto
No método acima, o & converte o bloco passado para o método em um objeto e armazena esse objeto no bloco variável local. De fato, podemos mostrar que ele tem o mesmo comportamento que o lambda e o Proc.new:
Isso é importante. Quando você passa um bloco para um método e o converte usando &, o objeto que ele cria usa Proc.new para fazer a conversão.
Observe que eu evitei o uso de "proc" como uma opção. Isso porque Ruby 1.8, é o mesmo que lambda e no Ruby 1.9, é o mesmo que Proc.new e em todas as versões do Ruby deve ser evitado.
Então você pergunta qual é a diferença entre lambda e Proc.new?
Primeiro, em termos de passagem de parâmetro, o lambda se comporta como uma chamada de método. Irá gerar uma exceção se você passar o número errado de argumentos. Por outro lado, o Proc.new se comporta como atribuição paralela. Todos os argumentos não utilizados são convertidos em zero:
Segundo, lambda e Proc.new tratam a palavra-chave return de maneira diferente. Quando você faz um retorno dentro do Proc.new, ele realmente retorna do método anexo, ou seja, do contexto circundante. Quando você retorna de um bloco lambda, ele apenas retorna do bloco, não do método envolvente. Basicamente, ele sai da chamada para o bloco e continua a execução com o restante do método anexo.
Então, por que essa diferença comportamental? O motivo é que, com o Proc.new, podemos usar iteradores dentro do contexto de métodos anexos e tirar conclusões lógicas. Veja este exemplo:
Esperamos que, quando invocarmos o retorno dentro do iterador, ele retornará do método envolvente. Lembre-se de que os blocos passados para os iteradores são convertidos em objetos usando Proc.new e é por isso que quando usamos return, ele sai do método envolvente.
Você pode pensar em lambdas como métodos anônimos, eles isolam blocos individuais de código em um objeto que pode ser tratado como um método. Por fim, pense em um lambda se comportando como um método anômalo e Proc.novo se comportando como código embutido.
fonte
Um post útil sobre guias de rubi: blocos, procs e lambdas
fonte
as diferenças entre proc e lambda é que proc é apenas uma cópia do código com argumentos substituídos por sua vez, enquanto lambda é uma função como em outros idiomas. (comportamento de retorno, verificações de argumentos)
fonte