Subsecciones

Aplicación Parcial de Funciones

Se denomina aplicación parcial al proceso de tomar una función y un fijar un subconjunto de sus argumentos a ciertos valores produciendo una función que es equivalente a la anterior sobre el conjunto de argumentos libres.

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

Ejemplo de uso:
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


Práctica: Aplicación Parcial

Extienda el módulo 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-06-18