

Haskell style list comprehensions in Ruby - ldubinets
https://gist.github.com/andkerosine/3356675

======
wedesoft
Somewhat related: I've developed a library for operations involving multi-
dimensional arrays [1, 2]. When possible it uses GCC for jit-compilation to
achieve higher performance.

    
    
      require 'multiarray'
      include Hornetseye
      # Object
      lazy(4) { |i| i + 2 }
      # Sequence(INT):
      # [ 2, 3, 4, 5 ]
      lazy(3, 2) { |x, y| x }
      # MultiArray(INT,2):
      # [ [ 0, 1, 2 ],
      #   [ 0, 1, 2 ] ]
      lazy(3, 2) { |x, y| x + 1 }
      # MultiArray(INT,2):
      # [ [ 1, 2, 3 ],
      #   [ 1, 2, 3 ] ]
      lazy(3, 3) { |x, y| y + 4 }
      # MultiArray(INT,2):
      # [ [ 4, 4, 4 ],
      #   [ 5, 5, 5 ],
      #   [ 6, 6, 6 ] ]
      lazy(3, 3) { |x, y| (x + 1) * (y + 4) }
      # MultiArray(INT,2):
      # [ [ 4, 8, 12 ],
      #   [ 5, 10, 15 ],
      #   [ 6, 12, 18 ] ]
      lazy { |x,y| Sequence['n', 'p', 'r', 't'][x] + Sequence['a', 'i', 'u', 'e', 'o'][y] }
      # MultiArray(OBJECT,2):
      # [ [ "na", "pa", "ra", "ta" ],
      #   [ "ni", "pi", "ri", "ti" ],
      #   [ "nu", "pu", "ru", "tu" ],
      #   [ "ne", "pe", "re", "te" ],
      #   [ "no", "po", "ro", "to" ] ]
      s = lazy(33) { |i| 3 * (i+1) }
      # Sequence(INT):
      # [ 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, .... ]
      s.mask((s % 2).eq(0)).collect { |i| i ** 2 / 3 }
      # Sequence(INT):
      # [ 12, 48, 108, 192, 300, 432, 588, 768, 972, 1200, 1452, 1728, .... ]
    

[1] <https://github.com/wedesoft/multiarray> [2]
<http://www.wedesoft.de/hornetseye-api/>

------
tome
It's neat that Ruby has programmable syntax like this, but Haskell's
comprehensions are one of its worst syntactic features IMHO. They're
inherently non-composable.

~~~
nimish
They're equivalent to do-notation in the List monad so as long as you don't
really need the inline syntax you can just mechanically translate it to do
nation and back.

And with -XMonadComprehensions you can have the compiler do that for a whole
bunch more Monads.

~~~
surement
It's also possible to just use Applicative with <*> and <$>

------
VeejayRampay
Cue to Haskell people lamenting the fact that this is an abomination and not
by any means "Haskell-style list comprehensions".

Still very nice though.

~~~
weareconvo
Haskell person here... I personally find Haskell list comprehensions to be
ridiculously ugly, and are an unnecessary bit of syntactic sugar over the List
Monad.

~~~
dons
... you might want to read up on monad comprehensions :)

<http://hackage.haskell.org/trac/ghc/wiki/MonadComprehensions>

~~~
weareconvo
Okay, as much as I hate syntactic sugar... that's pretty freakin awesome.

------
andkerosine
This has no business being at the top of HN.

~~~
Osmium
Why not? Seems pretty damn cool to me.

Edit: didn't realise you were the author :)

~~~
andkerosine
As its creator, I would certainly agree. Still, I'd feel bad if some poor soul
considered it anything but an interesting demonstration of Ruby's
capabilities.

~~~
zerr
Btw, it would be great if you add some comments there. What are the key (all
of it?) parts? etc...

------
egonschiele
Oh wow, that is so wrong and so beautiful.

------
dopamean
As someone who is still learning Ruby and would like to learn Haskell I have
no idea what is going on here. Would someone be kind enough to explain?
Thanks.

~~~
phaer
It's just adding a syntactic construct to ruby which looks similar to haskells
list comprehensions. Explanation for haskell:
[http://learnyouahaskell.com/starting-out#im-a-list-
comprehen...](http://learnyouahaskell.com/starting-out#im-a-list-
comprehension)

~~~
dopamean
Ah, I get it. Thanks dude.

------
gbog
Side question, rant. I love the syntactic side of list or dict comprehension
(in python) and often use them but as soon as I have to debug or expand the
functionality, I have to slice them into for loop. And then I hate myself for
being lazy/clever and more and more, when I start typing a = [, I hear an
internal voice: wait, aren't you being wrongfully clever one again?

I am the only one?

~~~
obviouslygreen
I adore list comprehensions, but perhaps for this reason, I generally only use
them for operations so simple as to be trivially correct or incorrect without
any debugging.

Dict comprehensions are just a little muddier, even for simple things, but a
single line of debug output after the comprehension should confirm whether or
not you're getting the structure you expect, provided you are still doing only
trivial work inside your comprehension.

------
stiff
Wow, that's some nontrivial Ruby, some explanation of this code would be nice,
I program in Ruby for some 6 years now and I still had to do a lot of head-
scratching to more or less figure this out. I had no idea Ruby allows
overloading of prefix operators, for example.

~~~
saraid216
There is an excellent book called "Metaprogramming Ruby" I'd recommend.

