Raw idea about Proc


#1

Hi all.

There is the idea (in VERY dirty code):

class Proc
def bound; @bound ||= {} end
def bind(num, val)
bound[num - 1] = val
end

alias :old_arity :arity
def arity
old_arity - bound.size
end

alias :old_call :call
def call(*arg)
bound.to_a.reverse_each{|num, val| arg.insert(num, val)}
old_call(*arg)
end
end

Usage:

l = lambda{|a,b,c| puts “a=#{a}, b=#{b}, c=#{c}”}

puts l.arity #=>3

l.bind(2, ‘b’)

puts l.arity #=>2

l.call(‘a’, ‘c’) #a=a, b=b, c=c

Two questions:

  1. Does somebody think it is useful?
  2. Does somebody already done this in some library?

Thanks.

Victor.


#2

On May 8, 2006, at 9:07 AM, Victor S. wrote:

Two questions:

  1. Does somebody think it is useful?

Yes, this is called Currying and has been written about a lot.

  1. Does somebody already done this in some library?

http://rubymurray.rubyforge.org/

Hope that helps.

James Edward G. II


#3

From: James Edward G. II [mailto:removed_email_address@domain.invalid]

On May 8, 2006, at 9:07 AM, Victor S. wrote:

Two questions:

  1. Does somebody think it is useful?

Yes, this is called Currying and has been written about a lot.

Oh, I know. The question meant “is this concrete extension would be
useful
for this concrete Ruby?” :slight_smile:

  1. Does somebody already done this in some library?

http://rubymurray.rubyforge.org/

Thanks, just what I’ve looked for.

Hope that helps.

Yeah, it did. :slight_smile:

James Edward G. II

Victor.


#4

On May 8, 2006, at 9:07 AM, Victor S. wrote:

Two questions:

  1. Does somebody think it is useful?

Yes, this is called Currying and has been written about a lot.

  1. Does somebody already done this in some library?

http://rubymurray.rubyforge.org/

cough :slight_smile: I’d like to quote from the docs at the moment where I lost
the plot…

“You have a hole in your curried subroutine but want to add more spices
after or fill out holes after your first hole.”

“Assuming no special spice before the hole, just put a hole in the
hole.”


#5

On Mon, 2006-05-08 at 23:07 +0900, Victor S. wrote:

alias :old_arity :arity
def arity
old_arity - bound.size
end

alias :old_call :call
def call(*arg)
bound.to_a.reverse_each{|num, val| arg.insert(num, val)}
old_call(*arg)
end
end

There are a few drawbacks to this approach I think, most of which I
forget right now. A probable biggie is that it won’t work with yield:

l = lambda { |num,ele| p num, ele }
l.bind(0,10)

[1,2].each &l

1

nil

2

nil

Maybe check out http://rubymurray.rubyforge.org , which does similar
stuff but by wrapping up the proc (still has limitations, but there you
go…)


#6

From: Ross B. [mailto:removed_email_address@domain.invalid]

end

There are a few drawbacks to this approach I think, most of which I
forget right now. A probable biggie is that it won’t work with yield:

Yes, I know (and disclaimer said about “VERY dirty code”). I’ve just
tried
to show raw idea about providing arguments-binding functionality.

RubyMurray which you and James have pointed to, is quite good for this.

Ross B. - removed_email_address@domain.invalid

Victor.


#7

l = lambda{|a,b,c| puts “a=#{a}, b=#{b}, c=#{c}”}

puts l.arity #=>3

l.bind(2, ‘b’)

puts l.arity #=>2

l.call(‘a’, ‘c’) #a=a, b=b, c=c

Two questions:

  1. Does somebody think it is useful?
  2. Does somebody already done this in some library?
  1. Binding parameters is useful sometimes.
  2. Do you really need this, considering how simple it is to create a new
    proc:

adder = proc { |a,b| a+b }
add_3 = proc { |a| adder.call(a,3) } # adder bound with b=3

Or, if you insist to keep with adder (bad idea IMHO):

_adder = adder.dup
adder = proc { |a| _adder.call(a,5) }

That said, there are situations a library based approach is useful.
I’d prefer solutions that create new proc objects without the bound
parameters, much like I did above manúally:

add_7 = bind_2nd(adder, 7)
add_7.call(1) ==> 8

add_11 = bind_nth(adder, 1, 11)
add_11.call(1) ==> 12

You will need to implement bind_* somewhere. If you do it in Proc, this
will look almost like your sketch:

add_13 = adder.bind_1st(13)
add_13.call(1) ==> 14
adder.call(10,7) ==> 17 # still works!

Creating a new proc should perform better than processing your bound[]
array every time #call is executed, and references to your proc in
other places don’t stop working because of unexpected arity changes.
A rock hard implementation probably needs some eval-trickery, and should
allow assignment back to self:

adder = adder.bind_2nd(-1) # really a decrementer now …

Jürgen


#8

From: Juergen S. [mailto:removed_email_address@domain.invalid]

Two questions:

  1. Does somebody think it is useful?
  2. Does somebody already done this in some library?
  1. Binding parameters is useful sometimes.
  2. Do you really need this, considering how simple it is to create a new
    proc:

adder = proc { |a,b| a+b }
add_3 = proc { |a| adder.call(a,3) } # adder bound with b=3

Unfortunally, this wouldn’t work in statements like:

adder = proc { |a,b| self.output(a+b) }
add_3 = proc { |a| adder.call(a,3) } # adder bound with b=3

class A
def output(val)
puts val
end
end

A.new.instance_exec(4, &add_3) #want to output 4+3, but receive
#undefined method `output’ for main:Object (NoMethodError)

Also, this bounding is less clear (somebody who would read my code,
would
may to think “WTF? Why this strange new proc?”

So, library approach is better.

That said, there are situations a library based approach is useful.
I’d prefer solutions that create new proc objects without the bound
parameters, much like I did above manúally:

add_7 = bind_2nd(adder, 7)
add_7.call(1) ==> 8

add_11 = bind_nth(adder, 1, 11)
add_11.call(1) ==> 12

I dislike the code above. Why? Because it is not very object-oriented. I
think this way: @I do the operation with Proc, so, the most natural way
should be Proc#some_operation". Also, bind_1st, bind_2nd are C+±like,
but I
don’t understand why we need such specialized methods in Ruby.

At the moment, RubyMurray’s approach seems to me as the most natural:

adder = proc { |a,b| self.output(a+b) }
add_3 = adder.curry(Curry::HOLE, 3)

Here is no need to think about argument’s numbers. I just provide
bounding
in the same order as arguments was.

Jürgen

Victor.


#9

On Mon, 2006-05-08 at 23:43 +0900, removed_email_address@domain.invalid wrote:

cough :slight_smile: I’d like to quote from the docs at the moment where I lost
the plot…

“You have a hole in your curried subroutine but want to add more spices
after or fill out holes after your first hole.”

“Assuming no special spice before the hole, just put a hole in the hole.”

Yeah, in truth it took me longer to figure out what the original Perl
docs were on about than it did to port the library :slight_smile: Happily though the
basic usage is pretty simple - just arguments and possibly regular
holes. You wouldn’t need to be combining spice and using the other
special spices most of the time.


#10

On Tue, May 09, 2006 at 03:42:07PM +0900, Victor S. wrote:

A.new.instance_exec(4, &add_3) #want to output 4+3, but receive
#undefined method `output’ for main:Object (NoMethodError)

Also, this bounding is less clear (somebody who would read my code, would
may to think “WTF? Why this strange new proc?”

If I’d ever see code like A.new.instance_exec(4, &adder) and I’d have
to guess this will, because of currying elsewhere, add 4+3 and call
some output function with the result in a rebound environment, my team
would hear me screaming in their beds. add_3 is a new proc, because it
does something new, with a different set of parameters.

Note the original example didn’t use class methods, and didn’t access
self. self in your first line will be bound to the closed over
environment (of Object), which is probably not wanted, since this
environment has no #output (as of the error message). If you’d want
currying of object methods, extend and use (Unbound)Method not
Proc. Methods support rebinding to objects without #instance_exec too.
Don’t blame my code for gross missapplication.

If you really want adder to call #output on something you don’t know
yet when defining the Proc, why not pass that as additional parameter
and forego the (not even in 1.8.4) #instance_exec magic that way? And
please, name accordingly if you really want clarity:

output_sum = proc { |dest,a,b| dest.output(a+b) }
output_add3 = proc { |dest,a| output_sum.call(dest,a,3) }
output_sum.call(A.new,1,2) # prints 3
output_add3.call(A.new,2) # prints 5

If you need to vary the curried parameter and dont’t want to create a
mass of procs, remember procs are closures:

n = 5
output_add_n = proc { |dest,a| output_sum.call(dest,a,n) }
output_add_n.call(A.new,2) # prints 7
n = 6
output_add_n.call(A.new,2) # prints 8

I think this way: @I do the operation with Proc,
so, the most natural way should be Proc#some_operation". Also,
bind_1st, bind_2nd are C+±like, but I don’t understand why we need
such specialized methods in Ruby. At the moment, RubyMurray’s
approach seems to me as the most natural: adder = proc { |a,b|
self.output(a+b) } add_3 = adder.curry(Curry::HOLE, 3) Here is no
need to think about argument’s numbers. I just provide bounding in
the same order as arguments was.

I was thinking functional, as asked for in the original
post. Sometimes a functional approach is quite appropriate. Currying
object methods (or Procs #instance_exec’d), thereby redefining their
interface, isn’t clean object oriented design either. Contrary to the
traditional functional application, it introduces lots of confusion
for small benefit. Classes already have internal state and behaviour
depending on message/method name, so no need to reimplement this. It
might be useful for some hackish duck typing, but why not just reopen
the class, or derive a new one, or add a singleton method, or refactor
your proc to a proper, object oriented class? Mabye your first thought
was faulty already, why keep using a Proc?

class MyCalc
def add(a,b) a+b end
end

class MyCalc
attr_writer :n
def add_n(a) add(a,@n) end
end

c = MyCalc.new # instead of a Proc we create a MyCalc
c.n = 3 # instead of currying, set an attribute
A.new.output(c.add_n(4)) # proper delimination of interfaces: MyCalc
# does the adding of n, A does the output.

Those last 3 lines can be understood by anyone without knowledge of a
library, and seem to do exactly what your example requried. And I bet
it is much faster too. It might be slightly more verbose, but
that’s a feature given the clarity and performance improvement.

To answer the original question again: Currying is sometimes useful
and powerful for simple functions, and you don’t need a library for
this. Currying of object methods, or currying of procs to mimic the
behaviour of classes, is at most a last resort solution, try something
else before it if you value your sanity.

Jürgen