ruby-1.9.2-head :013 > product = lambda { |x, y| x * y } # A function of two arguments
=> #<Proc:0x007fbf53991668@(irb):13 (lambda)>
ruby-1.9.2-head :014 > double = lambda { |y| product[2, y] } # Fix one argument, vary the other
=> #<Proc:0x007fbf530a9de8@(irb):14 (lambda)>
ruby-1.9.2-head :015 > double[4]
=> 8
En esta sección extendemos el módulo Functional con dos operaciones
lambda >> expresion retorna una lambda en la que se ha fijado el primer
argumento a expression
lambda << expresion retorna una lambda en la que se ha fijado el último
argumento a expression
if __FILE__ == $0
p = lambda {|x,y,z| x*y-z}
d = p >> 2 >> 3 # x = 2 y = 3
puts d[1] # 5 = 2*3-1
f = p << 4 << 5 # z = 4 y = 5
puts f[2] # 6 = 2*5-4
end
Implementación:
[~/TheRubyProgrammingLanguage/Chapter6MethodsProcsLambdasAndClosures]$ cat functional_partial.rb
require "./functional_compose"
module Functional
def apply_head(*first)
lambda {|*rest| self[*first.concat(rest)]}
end
def apply_tail(*last)
lambda {|*rest| self[*rest.concat(last)]}
end
alias >> apply_head # g = f >> 2 -- set first arg to 2
alias << apply_tail # g = f << 2 -- set last arg to 2
end
En Ruby 1.9 la clase Proc dispone del método curry. El método retorna un curried proc. Un curried proc si no recibe suficientes argumentos retorna un proc parcial sobre el resto de los argumentos:
ruby-1.9.2-head :006 > b = proc {|x, y, z| x+2*y-z }
=> #<Proc:0x007fac98842cd0@(irb):6>
ruby-1.9.2-head :007 > c = b.curry
=> #<Proc:0x007fac88828278>
ruby-1.9.2-head :009 > c[1,2,3]
=> 2
ruby-1.9.2-head :010 > c[1,2]
=> #<Proc:0x007fac88913688>
ruby-1.9.2-head :011 > c[1,2][3]
=> 2
Functional de manera que el operador ** admita como segundo argumento
un objeto hash cuyas claves son las posiciones de los argumentos que se desean fijar y cuyos valores indican
las expresiones a las que deben ser fijadas:
p = lambda {|x,y,z,w=0| x*y-z+w }
d = p ** {0 => 1, 2 => 3} # x = 1 z = 3
puts d[4] # 1 = 1*4-3+0
Casiano Rodriguez León 2015-01-07