Class: Proc

Inherits:
Object show all
Defined in:
lib/core/facets/proc/bind.rb,
lib/core/facets/proc/curry.rb,
lib/core/facets/proc/update.rb,
lib/core/facets/proc/bind_to.rb,
lib/core/facets/proc/compose.rb,
lib/core/facets/proc/partial.rb,
lib/core/facets/proc/to_method.rb

Instance Method Summary collapse

Instance Method Details

#*(x) ⇒ Object

Operator for Proc#compose and Integer#times_collect/of.

a = lambda { |x| x + 4 }
b = lambda { |y| y / 2 }

(a * b).call(4)  #=> 6
(b * a).call(4)  #=> 4

CREDIT: Dave



29
30
31
32
33
34
35
36
37
38
39
# File 'lib/core/facets/proc/compose.rb', line 29

def *(x)
  if Integer===x
    # collect times
    c = []
    x.times{|i| c << call(i)}
    c
  else
    # compose procs
    lambda{|*a| self[x[*a]]}
  end
end

#bind(object) ⇒ Object

Bind a Proc to an object returning a Method.

NOTE: This version comes from Rails. The old Facets version used thread.rb, but I no longer think the implementaiton is thread critical. Please make a bug report if this proves wrong.



12
13
14
15
16
17
18
19
20
21
# File 'lib/core/facets/proc/bind.rb', line 12

def bind(object)
  block, time = self, Time.now
  method_name = "__bind_#{time.to_i}_#{time.usec}"
  object.singleton_class.class_eval do
    define_method(method_name, &block)
    method = instance_method(method_name)
    remove_method(method_name)
    method
  end.bind(object)
end

#bind_to(object) ⇒ Object

Bind a procedure to an object. This works wrapping instance_eval on the Proc object and then wrapping this in a new Proc.

a = [1,2,3]
p1 = Proc.new{ join(' ') }
p2 = p1.bind_to(a)
p2.call  #=> '1 2 3'


12
13
14
# File 'lib/core/facets/proc/bind_to.rb', line 12

def bind_to(object)
  Proc.new{object.instance_eval(&self)}
end

#compose(g) ⇒ Object

Returns a new proc that is the functional composition of two procs, in order.

a = lambda { |x| x + 4 }
b = lambda { |y| y / 2 }

a.compose(b).call(4)  #=> 6
b.compose(a).call(4)  #=> 4

CREDIT: Dave

Raises:

  • (ArgumentError)


14
15
16
17
# File 'lib/core/facets/proc/compose.rb', line 14

def compose(g)
  raise ArgumentError, "arity count mismatch" unless arity == g.arity
  lambda{ |*a| self[ *g[*a] ] }
end

#curry(*args) ⇒ Object

Curry Proc object into new Proc object.

TODO: Utilize Ruby 1.9’s #curry method.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/core/facets/proc/curry.rb', line 7

def curry(*args)
  if args.empty?
    idx = (0...arity).to_a
  else
    raise ArgumentError, "argument count is greater than prok.arity (#{args.size} > #{arity})" if args.size > arity
    raise ArgumentError, "arguments must be unique indexes" if args.uniq != args
    raise ArgumentError, "arguments must be indexes" if args.any?{ |a| !Fixnum===a }
    idx = (0...arity).to_a
    idx = args + (idx - args)
  end

  pro = self
  rec = ''
  idx.each do |i|
    rec << "proc { |a#{i}| "
  end
  rec << "pro["
  rec << (0...arity).to_a.collect{|i| "a#{i}"}.join(',')
  rec << "]"
  rec << "}" * arity

  instance_eval rec
end

#partial(*args) ⇒ Object

Convert a Proc object into new partial Proc object.

a = proc { |a,b,c| a+b+c }
b = a.partial(NA,2,NA)
b[1,3] #=> 6

Note, the #__ method, which used to be used in stay of NA, has been deprecated.

a = proc { |a,b,c| a+b+c }
b = a.partial(__,2,__)
b[1,3] #=> 6

++

This method is similar to Proc#curry.

CREDT Trans



24
25
26
27
28
29
30
31
# File 'lib/core/facets/proc/partial.rb', line 24

def partial(*args)
  Proc.new do |*spice|
    result = args.collect do |a|
      NA == a ? spice.pop : a
    end
    call(*result)
  end
end

#to_method(object, name = nil) ⇒ Object

Convert Proc to method.

object = Object.new

function = lambda { |x| x + 1 }

function.to_method(object, 'foo')

object.foo(1)  #=> 2


16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/core/facets/proc/to_method.rb', line 16

def to_method(object, name=nil)
  ##object = object || eval("self", self)
  block, time = self, Time.now
  method_name = name || "__bind_#{time.to_i}_#{time.usec}"
  begin
    object.singleton_class.class_eval do
      define_method(method_name, &block)
      method = instance_method(method_name)
      remove_method(method_name) unless name
      method
    end.bind(object)
  rescue TypeError
    object.class.class_eval do
      define_method(method_name, &block)
      method = instance_method(method_name)
      remove_method(method_name) unless name
      method
    end.bind(object)
  end
end