On Feb 16, 7:48 am, Trans <transf... gmail.com> wrote:
> On Feb 15, 8:10 pm, "Brian Mitchell"
<binar... gmail.com> wrote:
>
>
>
> > On Fri, Feb 15, 2008 at 5:06 PM, Trans
<transf... gmail.com> wrote:
>
> > > On Feb 15, 12:46 pm, Yukihiro Matsumoto
<m... ruby-lang.org> wrote:
> > > > Hi,
>
> > > > In message "Re: Proc#curry"
>
> > > > on Sat, 16 Feb 2008 02:35:23 +0900,
Trans <transf... gmail.com> writes:
>
> > > > |Is there a link where I can read about
how this new function works?
>
> > > > [ruby-dev:33676], if you don't mind
seeing Japanese
>
> > > > If you do mind, it's OK. 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 } } }
>
> > > > See?
>
> > > Yep. I see.
>
> > > It is rather trivial, I agree. Unfortunately
maybe too trivial because
> > > were stuck with the order of arguments. Or
doe curry take some
> > > argument to vary that? To clarify what I
mean, Facets has an
> > > implementation of curry, for both Proc and
Method, like so:
>
> > > proc {|x, y, z| x + y + z
}.curry(__,__,__)
>
> > > Of course I like your better in this case
BUT, it does allow:
>
> > > proc {|x, y, z| x + y + z }.curry(__,5,__)
>
> > > for:
>
> > > proc {|x| proc {|z| x + 5 + z } }
>
> > Isn't that partial application not currying per
say (one could curry
> > as a way to implement partial application)?
>
> I've also heard it called "partial currying".
I'd rather have a
> superset of funtionality then a subset. Currying is
about isolating a
> single argument. It doesn't dictate in which argument
to isolate. It
> could be x, y, or z, etc. Nor does it mean currying
every variable all
> the way down that line.
>
> If we give matz's curry function an arity-slot number
as an optional
> argument, then we could do it all like so:
>
> P = proc { |x,y,z| x+y+z }
> P.curry(1) => proc { |y| proc |x,z| x+y+z } }
>
> Which would then allow partial applicaiton via:
>
> P.curry(1)[5]
>
> A second argument could dictate the next level of
currying
>
> P.curry(1,1) => proc { |y| proc |z| proc |x| x+y+z
} }
Here is an example implementation:
class Proc
def curry(*args)
if args.empty?
idx = (0...arity).to_a
else
raise ArgumentError, "argument count is greater
than arity
(#{args.size} > #)" if args.size > arity
raise ArgumentError, "arguments must be unique
indexes" if
args.uniq != args
raise ArgumentError, "arguments must be
indexes" if args.any?
{ |a| !Fixnum===a }
idx = (0...arity).to_a
idx = args + (idx - args)
end
rec = ''
idx.each do |i|
rec << "proc { |a#| "
end
rec << "self["
rec << (0...arity).to_a.collect{|i|
"a#"}.join(',')
rec << "]"
rec << "}" * arity
instance_eval rec
end
end
Example:
>> a = proc { |x,y| x**y }
=> #<Proc:0x00002aae4fd50638 (irb):5>
>> b = a.curry(0)
=> #<Proc:0x00002aae4fd4b110 (eval):1>
>> c = a.curry(1)
=> #<Proc:0x00002aae4fd45aa8 (eval):1>
>> b[2][3]
=> 8
>> c[2][3]
=> 9
I'd appreciate suggestions for improvement, as I certainly
expect
there are a plenty.
T.
|