Re: [stack] Point free (pointless) programming in ruby? (fwd)
John Nowak <[email protected]>
| Newsgroups | gmane.comp.lang.concatenative |
|---|---|
| Message-ID | <[email protected]> |
On Jan 15, 2009, at 5:37 PM, John Carter wrote:
> On Tue, 13 Jan 2009, John Nowak wrote:
>
>> Languages like ML and Haskell work better because they have curried
>> functions.
>
> Actually Currying works quite well in Ruby...
>
> two_arg = lambda{|a,b| somefunc(a,b)}
>
> b="Some concrete value"
> one_arg = lambda{|a| two_arg.call(a,b)}
That is not currying. Unfortunately, this is something of a common
misunderstanding. A curried function is one that emulates taking more
than one argument by using many functions that take a single argument.
For example, here's a function in Haskell that adds three numbers:
foo = \x y z -> x + y + z
And here's *the exact same function* with a different name:
bar = \x -> (\y -> (\z -> x + y + z))
When you write the former, you're really doing the later. Both can be
called identically as they're exactly the same thing:
foo (1, 2, 3) -- 6
bar (1, 2, 3) -- 6
Because 'foo' and 'bar' are curried, we can do this to mean the *exact
same thing* once again; this is called partial application:
((foo 1) 2) 3 -- 6
((bar 1) 2) 3 -- 6
Additionally, Haskell offers a function for currying a function:
curry (\(x, y) -> x + y) == \x y -> x + y
And uncurrying:
uncurry (\x y -> x + y) == \(x, y) -> x + y
Now, you *can* write a curried function in Ruby like so:
baz = lambda{|a| lambda{|b| lambda{|c| a + b + c}}}
And call it as such:
baz.call(1).call(2).call(3) # 6
Unfortunately, it's quite painful.
I'm not sure where the confusion with respect to "curry" started.
Factor is an example of a language that unfortunately misuses the term.
>> Keep in mind that all existing concatenative languages make heavy use
>> of stacks. Related languages like FP and FL make heavy use of lists.
>> Trying to do pointfree programming in languages that don't do such
>> things (Ruby, Python, Haskell, Scheme, etc) is going to be quite
>> painful. For example, here's the Haskell example above in Joy:
>
> Well, actually Ruby has Array's that behave (or can be made to behave)
> in almost all respects like lists.
Yes, you could write all new functions that operate on stacks instead
of using normal parameters. Ruby performance being what it is though,
I can't imagine this being useful for much of anything. Languages like
Factor do analysis to eliminate constant reading from and writing to a
stack which improves performance dramatically. Having to update an
array's contents, make bounds checks, update an array's length, and so
on just to add two numbers doesn't sound like fun.
> ie. Ruby is a superset of concatenative languages.
> ie. If one restricts ones activities to a suitable concatenative
> subset, the same interesting properties emerge.
Yes, if you rewrite every function to work on stacks and use none of
Ruby's features, you will have a very poor concatenative language with
awful syntax. Of course, one can implement Ruby's features in a
concatenative language too. It's therefore a bit silly to claim one is
a superset of the other.
- John