Thursday, June 11, 2009

And my CS adventure of the day

Today I suddenly realized that I could curry in Ruby (I was using the 1.8.6 framework at the time, so I'd have to write my own method).

Currying is basically the concept that you can decompose a function...

e.g. f(x,y,z) = x + 2y + 3z

...into...

g(x) = x + h(y)
where h(y) = 2y + i(z)
where i(z) = 3z

Now obviously I feel a need to show off my new found skills, so I thought to myself, when would this ever be useful? I asked around and nobody seemed to have a good answer. At that point, Google was my only recourse and to my delight it actually returned a thread on Ruby Forum.

Apparently Ruby 1.9.1 has a curry method built-in (also some new syntax, which is nice) and people there were trying to figure out what it's good for.

"It's not difficult at all,
proc {|x, y, z| x + y + z }.curry
returns the proc object equivalent to
proc {|x| proc {|y| proc {|z| x + y + z } } }"

"Uh, how do we call that?
...proc{...}.call(x).call(y).call(z)
What problem does that solve?"

"this one:
plus_five = proc {|x,y,z| x + y + z }.curry.call(2).call(3)
plus_five[10] #=> 15"

I gave a good chortle at this point, because the not retarded way of doing the same thing would just be:

sum = proc{|x,y,z| x + y + x}
plus_five = proc{|x| sum[x,2,3]}
plus_five[10] #=> 15


Which is pretty much what people have been doing since forever in imperative languages. It's also more flexible because plus_five doesn't have to be {|x| sum[x,2,3]}, it could just as easily be {|y| sum[2,y,3]}.

So where does this leave me? Well, I still have no idea what use currying is for. I hope someone can give me a practical example outside of Lisp, because being able to do this:

f = proc{|a,b,c| a + b + c}.curry
g = f[1][2]
puts g[3] #=> Outputs 6


...is actually pretty cool.

No comments: