```> L?hett?j?: Matt Maycock <ummaycoc / gmail.com>
> Aihe: Re: Partial function application (was: Re: Binding precedence for first sym...)
>
> On Wed, 2 Feb 2005 02:50:44 +0900, Trans <transfire / gmail.com> wrote:
> > Douglas Livingstone wrote:
> > > How about this:
> > >
> > > def fun(z)
> > >    x = 1
> > >    y = 2
> > >
> > >    # unmodified original
> > >    x = x + y + z
> > > end
> > >
> > > Then you shouldn't need to worry about rewriting as they would act
> > > more like defult params.
> >
> > Nice.
>
> This isn't even what he was asking for, though.  The OP wanted a
> `saved arguments' thing like currying...  hardcoding in x and y is the
> same as hardcoding 1 and 2 in the q (or x in OP's one example) = x +
> y+ z...
>
> Also, I've made a few small updates to my curry file, if anyone is
> interested (just default behaviors for certain methods invoked without
> any information to use).

Here's a naive, slightly more straightforward implementation
(entirely untested):

########################

# class Proc / Extension
# -- Extend Proc to enable currying.
#    If a block is invoked with too few arguments, it is
#    automatically converted to a 'new' block with the
#    given arguments bound to it in the fashion of currying.
#    If skipping an argument is desired, :_ can be used as
#    a placeholder:
#
#    p  = Proc.new {|a, b, c| a + b + c}
#
#    p1 = p.call(1, 2)       #  ~ Proc.new {|c| 1 + 2 + c}
#    p2 = p.call(1, :_, 3)   #  ~ Proc.new {|b| 1 + b + 3}
#
#    p.call(1, 2, 3)         # => 6
#    p1.call(3)              # => 6
#    p2.call(2)              # => 6
#
class Proc

alias :proc_init :initialize
alias :proc_call :call

# initialize / Constructor
# -- Create a normal Proc object and
#    initialize currying handling.
def initialize(&block)
# Initialize the block normally
proc_init &block

# Set up currying
ar = block.arity

# Block accepts any number of arguments?
@catchall if ar < 0

# Number of required arguments
@available = ar < -1 ? ar.abs : ar.abs - 1

# Set up the argument placeholders
@args = Array.new @available, :_
end

# Interface
public

# call / Interface method
# -- Attempt to execute the method. If all required
#    arguments have not been received, the block will
#    be executed, otherwise the block will be curried
#    from the collected arguments.
def call(*args)
# Bind the remaining arguments
bind_vars args

# Curry if all arguments are not present
return self if @available > 0

# Execute the block with the collected args
proc_call @args
end

# [] / Interface method
# -- Synonym for #call
alias :[] :call

# curry / Interface method
# -- Explicitly curries the block from the given args.
def curry(*args)
# Bind only
bind_vars args
end

# bind / Interface method
# -- Synonym for #curry
alias :bind :curry

# Internals
private

# bind_vars / Internal method
# -- Store the arguments given for future use.
def bind_vars(args)
# Ensure there are enough available slots
raise ArgumentError if (@available -= args.length) < 0 and not @catchall

# Replace the placeholders with the given arguments
@args.map! do |arg|
args.shift.dup if arg == :_ and
end

# Accept any remaining arguments if the block can take them
@args << args if @catchall
end

end  # class Proc

########################

The main issue, of course, is that extra syntax would be required
to be able to curry methods rather than blocks. Once either () becomes
overridable or something of that tune, this is more of a curiosity.

Then there's of course the age-old question whether this is in any
way a necessary addition to the language. It'd be nice to have an
end-all-be-all language but some features just don't jive together.
This one might.

> Given that the OP mentioned Haskell, I think we should all try to come
> up with some language that has the wonderfulness of Haskell with the
> wonderful ness of Ruby.  We could call it Rascal.  Since Haskell cats
> are all about domain specific languages, we could call DSLs in Rascal
> "Little Rascals"...  :-)

Apparently merd (www.merd.net) is trying to fill this niche. The
documentation is very sparse, though.

> ~Me!

E

```