# This method creates a proc from a block def makeproc(&p) # Convert associated block to a Proc and store in p p # Return the Proc object end
Como retorna un Proc podemos usarlo como una suerte de constructor:
adder = makeproc {|x,y| x+y }
sum = adder.call(2,2) # => 4
p = Proc.new {|x,y| x+y }
Si Proc.new es invocado sin bloque desde el interior de un método que tiene asociado un bloque entonces retorna un Proc representando al bloque asociado.
Así pues, estos dos métodos son equivalentes:
def invoke(&b) def invoke b.call Proc.new.call end end
is_positive = lambda {|x| x > 0 }
En Ruby 1.9 proc
es un sinónimo de Proc.new
ruby-1.9.2-head :003 > f = proc { |x| x + 1} => #<Proc:0x007ff03c236b60@(irb):3> ruby-1.9.2-head :004 > f[2] => 3
En el estilo clásico:
succ = lambda {|x| x+1}En Ruby 1.9:
lambda
por ->
succ = ->(x){ x+1 }
succ.call(2) # => 3
La lista de argumentos puede incluir la declaración de variables locales que se garantiza no sobreescribirán a las variables con el mismo nombre en el ámbito que lo contiene:
# This lambda takes 2 args and declares 3 local vars f = ->(x,y; i,j,k) { ... }
Es posible dar valores por defecto a los argumentos:
zoom = ->(x,y,factor=2) { [x*factor, y*factor] }
Como en las declaraciones de métodos, los paréntesis son opcionales:
succ = ->x { x+1 } f = -> x,y; i,j,k { ... } zoom = ->x,y,factor=2 { [x*factor, y*factor] }
La lambda minimal que no toma argumentos y retorna nil
vendría dada por:
->{}
Un ejemplo de expresividad:
[12] pry(main)> class Proc [12] pry(main)* def *(other) [12] pry(main)* ->(*args) { self.call(other.call(*args)) } [12] pry(main)* end [12] pry(main)* end => :* [13] pry(main)> succ = ->x{x+1} => #<Proc:0x007fc7a2a2f460@(pry):28 (lambda)> [14] pry(main)> square = ->x{x*x} => #<Proc:0x007fc7a34df838@(pry):29 (lambda)> [15] pry(main)> ss = succ*square => #<Proc:0x007fc7a349f4b8@(pry):25 (lambda)> [17] pry(main)> ss[2] => 5 [18] pry(main)> ss = ->x{x+1} * ->x{x*x} => #<Proc:0x007fc7a3415100@(pry):25 (lambda)> [19] pry(main)> ss[2] => 5
Si queremos pasar una lambda a un método que espera un bloque
es necesario prefijarla de &
[21] pry(main)> data = [3,2,1,4,2] => [3, 2, 1, 4, 2] [22] pry(main)> data.sort {|a,b| b-a } # The block version => [4, 3, 2, 2, 1] [23] pry(main)> data.sort &->(a,b){ b-a } # The lambda literal version => [4, 3, 2, 2, 1]
Casiano Rodriguez León 2015-01-07