|
|
|
SearchCategories
Books by the AuthorOther Ruby Projects |
Currying
Posted over 2 years ago
in Higher-Order Ruby.
Note: This is the sixth article in my Higher-Order Ruby series. The previous articles can be found at the following links: All the examples in this chapter are trivially translated (switch Another interesting point about this chapter is how much of it is spent warring with Perl's syntax. MJD really struggles to introduce a block-like syntax for curried methods and is outright defeated in a couple of attempts. I really like how easily Ruby yields to our attempts to reprogram her, in sharp contrast to her sister language. Continuing that line of thought, here's my best effort at the Poor Man's Currying library:
Unlike the Perl, this feels like very natural Ruby to me. You could argue that I struggle with Ruby's syntax because it's not easy to curry a block-taking method, but that seems like a minor issue. (This is fixed in Ruby 1.9.) Here are examples of me playing with my toy:
I am purposefully trying to show the library's flexibility in these calls. The version in the book only supports currying a single argument at the front of the list. In 15 lines the Ruby version can completely rewrite arguments as it sees fit and it includes OO support. You be the final judge, but I stand by my claim that Higher-Order Perl is the quest to bring many Rubyisms to Perl. If you want to go deeper down the rabbit hole of currying in Ruby, I recommend you check out the Ruby library Murray. If you want to see a more Rubyish example of the |
|
|
|
The code is super clean, though i did need to get into 'functional programming mode' to get it (took me about 5 minutes to understand what was going on).
Currying is academically super interesting, but I think it's more useful in languages like haskell.
If I were to write a double lambda which curried a multiply lambda, for instance, I'd just do this:
I think this is a lot less scary than a generalized currying lib, and just as powerful.
Maybe I'm missing a killer use case though. The method aliasing is definitely cool:
But what does that get me over:
I think the problem with Ruby is it doesn't need stuff like this. :)
What I find strange is that the syntax for calling your curried function uses square brackets whereas the syntax for calling regular methods (like "puts", "chop") uses parens. It's an unfortunate aspect of Ruby's design. Python can do most of the same tricks but both the input and the output of the curry are Python "callables" called with parens.
http://www.python.org/dev/peps/pep-0309/
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52549
In Python:
According to the Python docs, partial could be implemented like this:
Note that this partial function supports both positional and keyword arguments.
Another interesting version looks like this:
http://www.xoltar.org/2003/jun/25/partialModule.html
He only used square brackets as a shortcut (i.e. Proc#[] is an alias to Proc#call).
You can replace the square brackets "[...]" in his example with ".call(...)" and things will work just the same.