module Flt::Solver::Function

Some utilities to work with functions defined by blocks or lambdas, and defining parameter values with hashes without the need to redundantly define the names of the parameters. Currently works only with Ruby >= 1.9.2 (it uses Proc#parameters).

Examples:

f = Function.with_named_parameters(){|x,y,z| puts "x=#{x} y=#{y} z=#{z}"}
f[x:100, y:200, z:300] # => "x=100 y=200 z=300"
f = Function.bind(:x=>1000,:z=>2000){|x,y,z| puts "x=#{x} y=#{y} z=#{z}"}
f[5000] # => "x=1000 y=5000 z=2000"
f[6000] # => "x=1000 y=6000 z=2000"

Or, with Function[] syntax:

f = lambda{|x,y,z| puts "x=#{x} y=#{y} z=#{z}"}
Function[f][x:100, y:200, z:300] # => "x=100 y=200 z=300"
f = Function[f, :x=>1000, :z=>2000]
f[5000] # => "x=1000 y=5000 z=2000"
f[6000] # => "x=1000 y=6000 z=2000"

Public Class Methods

[](*args, &blk) click to toggle source

Shortcut for Function.bind or Function.with_named_parameters

Function[f=lambda{|a,b,c|...}, :a=>1,:c=>2] => lambda{|x| f[1,x,2]}
Function[:a=>1, :c=>2, &lambda{|a,b,c|...}]          => lambda{|x| f[1,x,2]}
Function[f=lambda{|a,b,c|...}] =>  lambda{|params| f[params[:a], params[:b], params[:c]]}
Function[&lambda{|a,b,c|...}]         =>  lambda{|params| f[params[:a], params[:b], params[:c]]}

Note that this syntax is not admitted by Ruby:

Function[:a=>1, :c=>2]{|a,b,c|...}
Function[]{|a,b,c|...}
# File lib/solver/function.rb, line 64
def self.[](*args, &blk)
  fun = args.shift unless args.first.kind_of?(Hash)
  parameters = args.shift
  if parameters.nil?
    with_named_parameters(fun, &blk)
  else
    bind(fun, parameters, &blk)
  end
end
bind(*args, &blk) click to toggle source

Returns a function by binding some of the arguments of a functor to values passed in a hash

Function.bind(f=lambda{|a,b,c|...}, :a=>1,:c=>2) => lambda{|x| f[1,x,2]}
Function.bind(:a=>1, :c=>2){|a,b,c|...}          => lambda{|x| f[1,x,2]}
# File lib/solver/function.rb, line 34
def self.bind(*args, &blk)
  fun = args.shift unless args.first.kind_of?(Hash)
  params = args.shift || {}
  fun = get(:bind, fun, blk)
  fun_parameters = parameters(fun)
  fun_args = fun_parameters - params.keys
  lambda do |*args|
    fun[*params.merge(Hash[fun_args.zip(args)]).values_at(*fun_parameters)]
  end
end
parameters(fun=nil, &blk) click to toggle source

Names of the parameters of a functor (block, Proc, etc.) (including optional and 'rest' parameters)

Function.parameters(lambda{|a,b,c|...}) => [:a, :b, :c]
Function.parameters{|a,b,c|...} => [:a, :b, :c]

Note that a block access through a &block variable is converted with Proc.new and this makes all arguments optional (or :rest). On the other hand if a lambda is passed as a block it retains the :req/:opt/attributes of its arguments.

# File lib/solver/function.rb, line 26
def self.parameters(fun=nil, &blk)
  fun = get(:parameters, fun, blk)  
  fun.parameters.select{|p,cls| cls!=:rest}.map{|p| p.last} # requires Ruby >= 1.9.2
end
with_named_parameters(*args, &blk) click to toggle source

Returns a function that takes parameters from a hash

Function.with_named_parameters(f=lambda{|a,b,c|...}) =>  lambda{|params| f[params[:a], params[:b], params[:c]]}
Function.with_named_parameters{|a,b,c|...} =>  lambda{|params| f[params[:a], params[:b], params[:c]]}
# File lib/solver/function.rb, line 48
def self.with_named_parameters(*args, &blk)    
  fun = args.shift unless args.first.kind_of?(Hash)
  fun = get(:with_named_parameters, fun, blk)
  lambda do |parameters|
    fun[*parameters.values_at(*parameters(fun))]
  end
end

Private Class Methods

get(mth, fun, blk) click to toggle source
# File lib/solver/function.rb, line 91
def get(mth, fun, blk)
  raise "Must pass either a proc/lambda or a block to #{mth}" unless fun || blk
  raise "Must pass only one of a proc/lambda or a block to #{mth}" if fun && blk
  fun || blk
end