Module: Flt::Solver::Function

Defined in:
lib/solver/function.rb

Overview

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"

Class Method Summary collapse

Class Method Details

.[](*args, &blk) ⇒ Object

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|...}


64
65
66
67
68
69
70
71
72
# 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) ⇒ Object

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]}


34
35
36
37
38
39
40
41
42
43
# 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) ⇒ Object

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.



26
27
28
29
# 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) ⇒ Object

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]]}


48
49
50
51
52
53
54
# 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