Ruby Idioms, Part 2

Written on 7:21:00 PM by S. Potter

Now the "idiom" we will use is not specific to Ruby, since I am pretty sure Perl has one of the constructs we will use to solve the stated problem, but it is still idiomatic, since the majority of popular OO languages (static, dynamic or otherwise) do not have it (as far as I know). Also some consider this to be a sub-optimal idiom, because there is a terser way to do something like this. However, the idiom I recommend below is much more multi-purpose, though I will show the terser version for the trivial case. Firstly our Javafied Ruby code looks like the following for the problem at hand:

if not var
  var = "some text string"
end
# OR for a pure Java to Ruby translation with ZERO Rubification
if nil == var # of course "if var == nil" is equivalent too.
  var = "some text string"
end
Now this is the most trivial case of wanting to set a variable to a value only when it is nil. The Ruby idiom I advocate is much more multi-purpose than this trivial case, but there is an even terser Ruby idiom that is only applicable to this case, which I wanted to show you first. See below:
var ||= "some text string"
As you can see this is very terse, but my question is, is it readable? Well to many Rubyists it is, but this relies on expressionistic understanding of how Ruby works under the covers. On projects involving developers with varied skill levels, I would definitely prefer my proposal below. Now onto the more readable and more multi-purpose idiom that reads much more like my natural language (which is my preference in general):
var = "some text string" unless var
Now some of you may think this isn't as readable as it could be, I concur. I sometimes prefer to use something like the following, but consistency on a project is important in my view, so pick on and go with it:
var = "some text string" if var.nil?
Again it reads more naturally, at least to an English speaker. But I will admit I have found myself using the terser "or equals" idiom in favor of the above for the trivial case (but consistently on projects with other advanced Ruby developers). However, the "if var nil?" idiom can be used in more multi-purpose situations, not only when you wish to set a variable when it has a nil value (that is null to you Java heads). A non-trivial usage of the "unless" version of the idiom would be well suited to a code snippet that tries to do the following:
user_defined_fruits = ['apple', 'cantaloupe']
fruits = ['apple', 'banana']
user_defined_fruits.each do |fruit|
  if fruits.include? fruit
    fruits << fruit
  end
end
fruits #=> ['apple', 'banana', 'cantaloupe'] NOT ['apple', 'banana', 'apple', 'cantaloupe']
Now a better way of doing this with the "unless" version of the idiom would be:
user_defined_fruits = ['apple', 'cantaloupe']
fruits = ['apple', 'banana']
user_defined_fruits.each do |fruit|
  fruits << fruit unless fruits.include? fruit
end
As you see above the code is terser, while being as readable, if not more (in my opinion again). To me it feels much more like my natural language, which in my view is the thing to aim for. Again the as-terse-as-possible enthusiasts will love the following:
user_defined_fruits = ['apple', 'cantaloupe']
fruits = ['apple', 'banana']
fruits |= user_defined_fruits

If you enjoyed this post Subscribe to our feed

3 Comments

  1. piffler |

    a typo?
    I think your first fruit example isn't equivalent to the next two. Fruits comes out ["apple","banana","apple"] just because the condition should not be
    if fruits.include? fruit
    but rather
    if !fruits.include? fruit
    or whatever the idiomatic Ruby negation is.

     
  2. S. Potter |

    @piffler: quite right. It should be:
    >>> unless fruits.include? fruit
    instead of
    >>> if fruits.include? fruit

    Thanks for reading!:)

     
  3. flip |

    Even Yet Still Another idiom:
    fruits = (fruits + user_defined_fruits).uniq
    -- or to define fruit as a Set.

     

Post a Comment