Curry

M

matt

I searched google groups and couldn't find a decent currying
implementation, so I took a few minutes and wrote one. Here it is,
for anyone who wants it. Any comments (ie if I messed up something I
didn't realize) are welcome :)

class Proc
alias oldcall call

def curry(&callTest)
@curry, @args, @callTest = true, [], callTest
self
end

def ncurry(n)
curry {|*args| args.length > n}
end

def call(*args)
return oldcall(*args) if @curry.nil?

res, me, pass = @args + args, self, @callTest
return oldcall(*res) if @callTest.call(self, *res)

# the me is just to make things read easier...
p = Proc.new {|*args| me.send:)oldcall, *args)}
p.curry(&pass)
p.instance_eval {@args = res}
p
end

def[](*args)
self.call(*args)
end
end
 
S

Shashank Date

Replying to my own post :)
I googled for "ruby curry fuction" and the very first hit took me to: ^^^^^^ function
So how do I use it ?

p1 = Proc.new {|x,y| x+y}
p2 = p1.ncurry(2).call(10)
p p2.call(30) # => 40
^^^^^^^^ shanko
 
M

matt

I searched google groups and couldn't find a decent currying
implementation, so I took a few minutes and wrote one. Here it is,
for anyone who wants it. Any comments (ie if I messed up something I
didn't realize) are welcome :)

After receiving an email, I realized two things. I didn't explain
what my `decent' measure was, and there's no explanation of how to use
my code. Sorry, I have the flu and am naturally a bit absent minded
:) (Note that my original search consisted of a one page google web
search, and a search of google groups - I did see mention of how I
curry being done, but no impl reference).

I've seen the version posted on
http://www.rubygarden.org/ruby?FunctionalRuby and it doesn't tickle my
fancy because it only has one layer of application (granted, in most
fp, this is what curry does - but most lisp curry functions I've seen
are more flexible, and ruby is a syntaxed lisp with extras imo). I
also wanted it to work on procs - I use these a lot, a lot more than
methods -- and my reasons there are just personal style.

As far as how to use it, here is an example:

add5orMore = Proc.new {|a,b,c,d,e,*f|
res = 0
# I know inject, but I have 1.6.x w/o it,
# and don't like to post untested code
[a,b,c,d,e,*f].each {|g| res += g}
res
}.ncurry(5)

add5orMore[1,2][3][4,5,6] # yields 21
add5orMore[1,2][3][4,5,6,7] # yields 28
add5orMore[1,2][3][4,5,6][7] # yields 0 - bit reference :)

of course, call can be used instead of the indexer function. It of
course can be used with a method as in the following:

@i=1 # make sure instance data goes too :)
def add4(a,b,c,d)
a + b + c + d + @i
end

m = method:)add4).to_proc.ncurry(4)

puts m[2][4][6,8] # yields 21
puts m[2][4][6,8,10] # wrong # args error!

And there are obvious modifications to class Method go from
#to_proc#ncurry to #ncurry. The current version of my code is
available at http://www.cs.drexel.edu/~ummaycoc/curry.rb -- sorry if
I forgot anything this time, or have any errors, or for anything
undesirable really :)
 
S

Shashank Date

I also wanted it to work on procs - I use these a lot, a lot more than
methods -- and my reasons there are just personal style.

Yes, that is a great improvement. I like your version better :)
As far as how to use it, here is an example:

<snip>

Thanks a lot !
-- shanko
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top