Useful Perlisms in Ruby

  • Posted by Mike Naberezny in Ruby

    PHP syntax shows obvious similarities to Perl. For example, we have the prefixing of variables ($), the arrow for object access (->), and semicolons terminating our statements. While it’s perhaps less obvious to PHP developers at first, Ruby’s syntax has also been influenced by Perl in various ways.

    Ruby has quite a few interesting syntax features, some inspired by Perl and some not, that are sometimes lumped together as the “Perlisms” in Ruby. Let’s explore a few of the more useful ones you’ll likely encounter in Rails applications.

    Word Arrays

    Ruby has a very convenient syntax for arrays:

    days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri']
    

    However, if your array elements are words (no spaces), you can do one better.

    days = %w[Mon Tue Wed Thu Fri]
    

    The %w array modifier allows you to write more readable arrays of words by omitting the noise of the quotes and commas.

    Regular Expression Matches

    In PHP, regular expressions are written inside strings. These strings are passed to functions like preg_match() that perform the matching:

    $text = 'You have 12 new messages';
    
    if (preg_match('/(\d+) new/', $text, $matches)) {
      print "Found {$matches[1]} messages";
    }
    

    Ruby’s regular expressions aren’t written inside strings because they have a native syntax supported by the language. We can write the above example as:

    text = 'You have 12 new messages'
    
    if matches = /(\d+) new/.match(text)
      puts "Found #{matches[1]} messages"
    end
    

    Since /(\d+) new/ is itself an object, we can call the match method on it. The snippet otherwise looks similar to the PHP version.

    However, there’s another way:

    text = 'You have 12 new messages'
    
    puts "Found #{$1} messages" if text =~ /(\d+) new/
    

    You can use the =~ operator to test if a regexp matches and !~ to test if it doesn’t. Also, Ruby automatically assigns the regexp matches to special variables. $1 is the first match, $2 is the second match, and so on.

    Finally, we reversed the conditional to shorten the snippet a bit.

    Grouping Thousands

    Have you ever needed a fairly large numeric literal?

    bytes = 1048576
    

    You might appreciate that Ruby allows you to use underscores in numbers.

    bytes = 1_048_576   # Ruby's Grouping
    
    bytes = 1.megabyte  # Rails' ActiveSupport
    

    You can use the underscore to group thousands or whatever you like, and Ruby will just filter it out. For common numbers like byte multiples, Rails takes it to another level of readability with special methods like megabyte shown above.

    Parting Thoughts

    There’s quite a few other so-called Perlisms in Ruby. Some are great, and some aren’t so great. For example, you can access Ruby’s load path with the readable $LOAD_PATH variable or the cryptic $: variable. This post from Nick Seiger has some really obscure features of Ruby.

    Ruby’s language design makes programming very convenient, but it’s power is that its allows us to write intuitive programs that often read like natural language. When you abuse the syntax features, you only make code harder to read.

    Experienced PHP developers learn that there are some aspects of the PHP language, deprecated or not, that you might want to avoid for cleaner code. This is sometimes true of Ruby also, as with most programming languages.

    While the features demonstrated above are useful and popular, some features of Ruby aren’t popular in the Rails community at all. Most of the pre-defined variables that aren’t words fall into this category. In general, Rails developers always strive to write programs that are easier to understand and maintain.

    Becoming an effective Rails developer is not only learning the features of the Ruby language, but developing a sense of good taste for how to use those features.