--s2ZSL+KKDSLx8OML
Content-Type: text/plain; charset=iso-8859-1
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Tue, May 09, 2006 at 03:42:07PM +0900, Victor Shepelev wrote:
> 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?"

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.

Jgen

-- 
 The box said it requires Windows 95 or better so I installed Linux

--s2ZSL+KKDSLx8OML
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: Digital signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (GNU/Linux)

iQEVAwUBRHQxX/y64gyiEfXtAQIbTQgA8MPnoZ2BZzvCbIRGENeCwYJv+5xmnnKd
JU1NT0+GLA/ouGUkpPuUBrjhk8z4pFv9D6K5Ow9kav5VkP7WJxYwdPJIm5wN65Kf
AhoeI3MsOC0pHzKyerY1hkzPn7H8lFZqhPCmgIB8NW1iGmkikt8RPs6bVm3W4F/Q
fFBlOhaPrw/mKIJbNovj6yme1qBsooeShdN547IlL+wY26+7cpEwBlvCxm6UecI1
R8HDr/uy2H0/6EUSYk+B/+JckuJcgTeeYuP76jGXSGf40cb6RKh0zFjHh2R7HJNJ
eQ9dq/lpVJu7LDqYc6MmC7EtY6S2grVrFuZ0zGJ0J5F1fuNspDh16ABc
-----END PGP SIGNATURE-----

--s2ZSL+KKDSLx8OML--