On 5/18/06, Madan Manoharan <madan.manoharan / gmail.com> wrote:
> On 5/18/06, Joe Bowers <JoeBowers / bclip.com> wrote:
> >
> > Partials are great for deferring part of a computation
> > until later- they're useful in some of the same circumstances
> > as closures. They're also really easy to use in ruby already.
> >
> >   def multiply(x, y); x * y; end
> >
> >   multiply_by_3 = lambda { |x| multiply(3, x) }
> >
> >
> Yesterday* Brian Mitchell *introduced me to the work of *MenTaLguY* where he
> talks about 'Promise' and 'Future'; Future sounds very similar to partial
> functions.
>
> http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/6956dd6e4a00258

I did introduce that but it isn't quite right to call them the same
thing. One is delay of complete execution (Future/Promise) and the
other is delay for complete application of arguments (Partial
Application/Currying). There are, as mentioned, libraries that
implement currying in Ruby. There are also many ways to curry and many
semantics to chose (execution that is strict, eager, lazy, etc..).

I have used currying many times for real world things to specialize
the interface of some code while boosting the generic properties of
other code. I had curry extensions used in Rails validations for a
complex application. The plus came down to allowing me to write only a
handful (less than ten) core validators and have many more different
combinations actually used across some very rich models. This helped
me keep my code DRY and very maintainable.

Haskell, another beautiful language, makes good use of currying:

Jim's example in Haskell:
map (*3) [1,2,3]

To see even deeper we can check the infered type of (*) versus (*3):
(*) :: (Num a) => a -> (a -> a)
(*3) :: (Num a) => a -> a

Aside from explaining the syntax [1], you might notice that (*) is a
function which actually returns a function which returns a result on
that final application. So with this knowledge we could then take the
map example one step further:

mapMultBy3 = map (*3)
mapMultBy3 [1,2,3]

The type of mapMultBy3 is easily figured out by thinking of what you
pass in and get back out (lists of numbers):

mapMultBy3 :: (Num a) => [a] -> [a]

This parametric aggregation is really powerful when understood. It
also complements many other things like general high order programming
really well [2]. In the end it is useful in Ruby if the use is chosen
carefully (and sparingly). It may not be first class (for good reason
IMO) but as we've seen that is hardly a reason not to consider it in
some cases.

Hope this didn't get too confusing! </rambling>
Brian.

[1] I *highly* recommend people learn a _few_ functional programming
languages. Haskell is my favorite at the moment but others seem to
like OCaml and other ML dialects. Erlang is functional but is quite
different from Haskell and OCaml. Esoteric ones exist like Joy and
others that might be fun to check out. Last but not least, Scheme is
great for playing around with different combinations of things though
it doesn't always end up as clean as the above.

[2] There probably is a reason most FP languages feature some form of
currying ^^.