Syntax Changes in 1.9

Posted 2007-12-03…

I think one of the more interesting conversations that’s going to occur in the Ruby community once 1.9 is released is how we integrate the syntax (and behavioral) changes coming into the language in as elegant form as possible. Over time, the consensus (or at least conventional usage) will drive what we label Rubyesque (that is, idiomatically _Ruby_); what is accepted, what is absurd, what is clean, what is over-engineered, and what is far more clever than it is smart. We’ll be reforming the feel and taste of Ruby using new artistic tools.

Over time, we’re sure to see a lot of forms pop up and then slowly fade away (remember the days of def ClassName.method_name and :: method invocations?), we’ll see casual groups form (eg, the collectionists, the mappers, the private indenters, etc), and entirely new dialects pop out of the ether (Rails, anyone?) and seed the ground with fresh ideas.

This is nothing new. It’s how languages grow. Regardless of how you feel about it, Ruby is no exception.

Over the next few weeks I’m going to be switching the focus of this blog (wait, there was a focus?) to the Ruby 1.9 release, especially as it relates to the syntax changes.. since Ruby’s syntax is largely what drew me to the language, and something that continues to enthrall. This is definitely the most radical release I’ve seen so far (though it needs to be said that many of the changes are experimental), so I’m really going to dig in.

Let’s start with a few examples of experimental lambda and hash features currently in 1.9. I’ll be showing a few examples of some variants, it’s up to you to decide on the forms you like most. You might want to bone up on the changes first.

h4. The Strategy Hash

Example: Assigning a hash of symbol keys and lambda values as various strategies to process a string.

Flavors to choose from:

  1. Traditional ‘lambda’ (let’s skip ’proc’)
  2. Experimental arrow lambda, parameters outside (parenthesized)
  3. Experimental arrow lambda, parameters outside (bare)

Note that I’m syntax highlighting the following examples partially because I know it won’t work correctly
(since coderay currently only supports on 1.8 syntax).

strategies = { :simple => lambda { |item| item.capitalize } }
strategies = { :simple => ->(item) { item.capitalize } }
strategies = { :simple => -> item { item.capitalize } }

The arrow variants look [at least] a little less ridiculous with the special symbol-key syntax:

strategies = { simple: lambda { |item| item.capitalize } }
strategies = { simple: ->(item) { item.capitalize } }
strategies = { simple: -> item { item.capitalize } }

The Filter List

Example: Now let’s toss some text filtering lambdas into an Array, using the various flavors.

filters << lambda { |item| item.capitalize }
filters << ->(item) { item.capitalize }
filters << -> item { item.capitalize }

Whoa, love the opposing directions there.

Let’s push multiple arguments now:

filters.push lambda { |item| item.capitalize }, lambda { |item| item.reverse }
filters.push ->(item) { item.capitalize }, ->(item) { item.reverse }
filters.push -> item { item.capitalize }, -> item { item.reverse }

These filters would be fun with inject & the new experimental .() version of call/[]:

filters.inject('hey!') { |res, filter| filter.(res) }
# => "!yeH"

In parting, a bit of clever code (note Enumerator, Lambda syntax, single block parameter, alternate call syntax).

3.times.inject(-> { -> { -> { "Hello, #{RUBY_VERSION} World!" } } }){ |_| _.() }

There’s a lot more to cover, obviously, but that’s enough for now.