# Point free (pointless) programming in ruby? (fwd)

## John Carter — 2009-01-13 23:15:32

    Here's a post I sent to the ruby mailing list about doing pointfree /

    concatenative like things in Ruby.

    Perhaps some of the Denizens of this list might like to apply their

    wondrously creative minds to the exercise.

    John Carter                             Phone : (64)(3) 358 6639

    Tait Electronics                        Fax   : (64)(3) 359 4632

    PO Box 1645 Christchurch                Email : john.carter@...

    New Zealand

    ---------- Forwarded message ----------

    Date: Wed, 14 Jan 2009 12:12:00 +1300 (NZDT)

    From: John Carter <john.carter@...>

    To: ruby-talk ML <ruby-talk@...>

    Subject: Point free (pointless) programming in ruby?

    I'm very fond of the notion of Concatenative Languages such as Joy,

    Factor...

       http://en.wikipedia.org/wiki/Joy_(programming_language)

       http://www.latrobe.edu.au/philosophy/phimvt/joy/jp-joyjoy.html

       http://factorcode.org/

    There is a supreme simplicity about them.

    So while reading what the current state of them is, I stumbled across

    the notion of Point free (sometimes called Pointless) programming.

    The idea of sequences of function compositions that elide the

    arguments that they will be applied to.

    http://www.haskell.org/haskellwiki/Pointfree

    One can easily define a sequence of methods in Ruby...

    fun_seq =  [:a, :b, :c]

    as a sequence of symbols.

    Which one could apply to an arbitrary argument..

    irb

     > f = [:to_s, :succ]

     => [:to_s, :succ]

     > f.inject(4,:send)

     => "5"

    Oooh! Looky! That's sneaky of me!

       symbol_sequence.inject(arg,:send)

       [:a, :b, :c].inject(arg,:send)

    that's equivalent to

       arg.a.b.c

    Not quite function composition. Cute, but let's try...

    irb

     > def a(a)

    >  p ["a",a]

    > a+"a"

    > end

     => nil

     > def b(b)

    >  p ["b",b]

    > b+"b"

    > end

     => nil

     >  def c(c)

    > p ["c",c]

    > c+"c"

    > end

     => nil

     > f=[:a,:b,:c]

     => [:a, :b, :c]

     > f.inject("foo"){|memo,obj|send(obj,memo)}

     ["a", "foo"]

    ["b", "fooa"]

    ["c", "fooab"]

    => "fooabc"

    [:a, :b, :c].inject(arg){|memo,obj|send(obj,memo)}

      is equivalent to

    c(b(a(arg)))

     > c(b(a("bah")))

     ["a", "bah"]

    ["b", "baha"]

    ["c", "bahab"]

    => "bahabc"

    Or how about working with lambda's or Proc objects...

     > a1 = lambda {|x| x+"a"}

     => #<Proc:0xb7d9f744@(irb):41>

     > b1 = lambda {|x| x+"b"}

     => #<Proc:0xb7e0feb8@(irb):42>

     > c1 = lambda {|x| x+"c"}

     => #<Proc:0xb7dfa5e0@(irb):43>

     > [a1, b1, c1]

     => [#<Proc:0xb7d9f744@(irb):41>, #<Proc:0xb7e0feb8@(irb):42>,

    #<Proc:0xb7dfa5e0@(irb):43>]

     > [a1, b1, c1].inject("foo"){|memo,proc| proc.call(memo)}

     => "fooabc"

    Anyhoo! Clearly in principle one can do Pointfree programming Ruby.

    Questions for the Group:

    1) Is there a neater way of expressing a sequence of function

        compositions in Ruby?

    2) Which Ruby Pointfree sequences are actually useful?

    John Carter                             Phone : (64)(3) 358 6639

    Tait Electronics                        Fax   : (64)(3) 359 4632

    PO Box 1645 Christchurch                Email : john.carter@...

    New Zealand

## John Nowak — 2009-01-14 01:00:16

    On Jan 13, 2009, at 6:15 PM, John Carter wrote:

     > 1) Is there a neater way of expressing a sequence of function

    >    compositions in Ruby?

     Evaluation of a concatenative language is just a fold of 'apply' over

    your list of functions with the empty list as the initial element. For

    example, in Scheme:

        (define (ceval fs) (fold apply '() fs))

    Your Ruby version is essentially the same thing.

     > 2) Which Ruby Pointfree sequences are actually useful?

     All you can really do is implement a concatenative language inside

    Ruby complete with its own standard library. This is probably not so

    useful.

    Languages like ML and Haskell work better because they have curried

    functions. There even exists a tool for automatically translating

    pointful Haskell functions to point-free Haskell functions, although

    the results are often less than clear:

        \x y z -> y * z - x  ==  flip (flip . ((-) .) . (*))

    You may want to look at the following:

    http://www.haskell.org/haskellwiki/Pointfree

    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:

        * swap -

    And in a concatenative FP-style language:

        - [hd, * tl]

    - John

## John Carter — 2009-01-15 22:37:12

    On Tue, 13 Jan 2009, John Nowak wrote:

     > Languages like ML and Haskell work better because they have curried

    > functions.

     I wonder if Curried Functions have the same effect as Curried Eggs

    have on the digestive system?

    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)}

    one_arg.call("Single parameter") is equivalent to

    someFunc( "Single Parameter", "Some concrete value")

     > 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.

    The obj.a.b.c.d.e form would be effectively identical to the

    concantenative stack to stack functions if obj was an Array and each

    method a, b, c, d, e was a non-destructive Array method returning an

    Array.

    Well, actually Rubies Duck Typing extends that in interesting

    ways. See the Ruby Enumerable mixin for an example.

    ie. Ruby is a superset of concatenative languages.

    ie. If one restricts ones activities to a suitable concatenative

    subset, the same interesting properties emerge.

    The question then remains... What interesting idioms could one evolve

    by playing in that subset.

    John Carter                             Phone : (64)(3) 358 6639

    Tait Electronics                        Fax   : (64)(3) 359 4632

    PO Box 1645 Christchurch                Email : john.carter@...

    New Zealand

## John Nowak — 2009-01-16 00:00:21

    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

## John Carter — 2009-01-16 01:49:16

    On Thu, 15 Jan 2009, John Nowak wrote:

     > That is not currying. Unfortunately, this is something of a common

    > misunderstanding.

     You are right, sorry.

     > 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.

     Try an alternate syntax then...

    irb

    irb(main):001:0>  baz = lambda{|a| lambda{|b| lambda{|c| a + b + c}}}

    => #<Proc:0xb7d94ab0@(irb):1>

    irb(main):002:0> baz[1]

    => #<Proc:0xb7d94ba0@(irb):1>

    irb(main):003:0> baz[1][2]

    => #<Proc:0xb7d94c40@(irb):1>

    irb(main):004:0> baz[1][2][3]

    => 6

     > It's therefore a bit silly to claim one is a superset of the other.

     Perhaps a better way of putting it would given the very flexible

    multi-paradigm nature of Ruby, one can borrow the "Pointfree"

    paradigm as well.

    Will it be useful? Well, I suspect it might be.

    I haven't seen anything yet that has given me the urge to rip Ruby out

    as my main day to day programming workhorse. However there are parts

    of the concatenative languages that make feel "ooh that has so much

    promise... but not quite something I can convince my boss about".

    Ruby doesn't quite comfortably replace the *sh languages yet.

    One area that has been a bit hard to express is the *sh '|' pipelines.

    I'm playing with the idea of pointfree in ruby as a nice paradigm to

    do pipelined oneliners and more.

    John Carter                             Phone : (64)(3) 358 6639

    Tait Electronics                        Fax   : (64)(3) 359 4632

    PO Box 1645 Christchurch                Email : john.carter@...

    New Zealand

## John Nowak — 2009-01-16 01:57:02

    On Jan 15, 2009, at 8:49 PM, John Carter wrote:

     > I haven't seen anything yet that has given me the urge to rip Ruby out

    > as my main day to day programming workhorse.

     >> x = 0

     => 0

      >> x

     => 0

      >> lambda{|x| 0}.call(5)

     => 0

      >> x

     => 5

    That gave me the urge to do something alright.

    Yes, I realize it has been fixed. Unfortunately it took 12 years,

    which can only mean that those involved have no clue what they're

    doing. But now I'm just being rude...

    - John