Beautiful multi-line blocks in Ruby

“I need a new drug”:http://youtube.com/watch?v=MMSFX1Vb3xQ. One that won’t quit. One that will let me sensibly structure the use of blocks in Ruby such that they can run across multiple lines and yet still chain blocks together.

OK, so its not really a drug I need, per se. Though, I’m sure what Huey Lewis really needed was a new drug. But what I need is a convention, or perhaps some syntax. It should say to you, “HEY. Adam’s doing something clever with blocks here. Keep your eyes open.”

I find myself desiring a new syntax and/or convention, when using blocks. I’ve been trying to write in a more functional style lately, especially a pure-functional style wherein you never call a method for its side-effects. I don’t think I’m the only person doing this. Jim Weirich sort of alluded to it in a post about “when to use @do/end@ vs. braces”:http://onestepback.org/index.cgi/Tech/Ruby/BraceVsDoEnd.rdoc. Rick DeNatale “took it a step further”:http://talklikeaduck.denhaven2.com/articles/2007/10/02/ruby-blocks-do-or-brace. I want to lay it bare.

Let’s start with something innocuous:


ary = [1,2,3]

result = ary.map do |n|
  x = n * 4
end

result # => [4, 8, 12]

You get the value back of each object in the array, mapped to the result of calling the block. Fun times. Now, let’s put it on one line and do something clever with it.


ary.map { |n| n * 4 }.select { |n| n == 4 } # => [4]

Now we’re cooking! Ruby’s syntax allows us to chain methods and blocks. Which turns out nice in this case where I want to filter down the array of mapped values. But let’s pretend we need to do something clever in those blocks.

  
    ary.map { |n|
      n * 4
      # Some
      # clever
      # things...
    }.select { |n|
      n == 4
      # More
      # clever
      # things...
    }.any? { |n|
      n == 4
      # Gratuitiou
      # clever
      # things...
    } # true
  

That’s the best I could come up with for chained, multi-line blocks. It looks “Weirichian”. Despite that, it kinda makes me vomit in my mouth.

So, since “I got awesome feedback on my last question of taste”:http://therealadam.com/archive/2008/04/28/can-i-send-you-a-message/, I’m tapping you, my favorite Ruby developer, for more. The ground rules are that you can’t extract the logic into a real method and you can’t jam everything onto one line. You have to use multi-line blocks. What looks good to you here?

Adam Keys @therealadam