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