Ruby 101 for .NET developers: The strange ||= operator 15

Posted by jeff Tuesday, February 06, 2007 13:57:00 GMT

I admit I really didn't know what to title this... I just thought I'd start to write down all the little Ruby quirks that I've picked up over time that seemed odd to me at first, in an attempt to spare newcomers undue frustration when the read someone else's Ruby code (like the Rails source code, for example).

First, a question that comes up about once a week on the Rails list (and yet another reason I'm starting to drift away from the list... the same questions keep coming up all the time):

Sometimes in Ruby you'll come across some code that looks like this:

stuff ||= [ ]

or maybe

stuff ||= { }

What's going on here? First, if you're new to Ruby, you may not realize how the || operator really works, so let's digress for a minute and talk about that first. The || operator is a short-circuited logical OR operator. If I say

a = "hello"
b = a || "goodbye"

What is the value of b? It will be "hello". Since a evaluated to something that's not nil and not false, it stopped right there (short circuited itself) and assigned be a reference to a. But suppose a was nil instead:

a = nil
b = a || "goodbye"

Now, b will become "goodbye". Since a was nil, the OR operator continued to evaluate the next expression, which was "goodbye". So b becomes "goodbye".

If you're with me so far, then you're already rounding third base. Now, you probably already know that this:

a = a + 5

can be shortended to this:

a += 5

right? In Ruby, this same idea gets applied to the OR operator. Instead of writing this:

a = a || "baseball"

This means, if a already has a value, then keep it; but it it's nil, then assign it to "baseball". But horrors, what a lot of typing! A good Ruby programmer would do this instead and save two whole keystrokes:

a ||= "baseball"

In other words, a will become "baseball" if it was nil (or false) before, otherwise it will just keep its original value.

Make sense? Questions? Bring it on.

Comments

Leave a response

  1. Diego Guidi   February 07, 2007 @ 09:03 PM

    Ruby language is simply beautiful :)

  2. Jason Salas   February 07, 2007 @ 11:37 PM

    ||= is one of my favorite features of Ruby...it's got that time-saving sexiness that reminds me of why I prefer the ternary logic (i.e., if(something) ? "yes" : "no") of JavaScript and C# to earlier versions of VB.

  3. Derek   February 08, 2007 @ 02:10 AM

    Jason: Ternary operator. Not logic. A ternary operator takes three arguments. Ternary logic refers to situations where you have three possible results: "true/false/other value."

    I knew what you were talking about, but you used the wrong terminology. Sorry for being the ternary Nazi. I don't know why it bugged me. :)

  4. Max   February 08, 2007 @ 08:37 AM

    Yeah, this is one of the really good examples why Ruby is such a nice language. And I think I will recommend this blog to a friend of mine so he will learn the beauty of this language and reduce his .NET activity ;)

  5. Jeff   February 08, 2007 @ 02:19 PM

    @Diego: You said it well!

    @Max: Thanks - and yes, help us spread the word to our fellow .NET developers. Learning Ruby does not mean they have to give up .NET; to the contrary, I expect to see Ruby support in Visual Studio at some point (witness the Ruby.NET project that MS is funding, hiring away Ruby experts like John Lam, etc.)

  6. Marcus   February 09, 2007 @ 12:09 PM

    Thanks! Great explanation. I've got another question for you -- Proc I think I understand but lambda I don't get yet... I've read a couple explanations but it hasn't clicked enough for me to find myself using it in actual code yet.

  7. Jeff   February 09, 2007 @ 06:50 PM

    Marcus: I haven't used lambdas much either. The main difference between a lambda and a proc (as far as I can tell) is that a proc is kind of like a "snippet" of code: it's a closure, but the flow control around your proc are still in control. So if you put a "return" statement inside your Proc (or block), you will be returning from the enclosing function, not just from your block (which could be bad). On the other hand, a lambda is more of a first-class function unto itself, so a "return" statement inside your lambda will simply return from the lambda, and the containing function resumes normally. Lambdas can also be passed around and called at a later time, even after the method that created the lambda has left scope. So lambdas can be used across threads, for example, whereas procs can't.

    Most "mainstream" Ruby programming doesn't rely on these differences between lambdas and blocks, so you generally won't see the lambdas used in, say, Rails applications.
    I suppose if I was doing more functional-style programming, I might use it more - and in that case perhaps I might actually know what I'm talking about. :-)

  8. Steve   February 18, 2007 @ 04:33 PM

    Cool. It sounds like the || operator is the same as the null coalescing operator ?? in .NET 2.0. I'm not currently on my Mac with Parallels to checkout if ??= is supported, but it would be a nice addition if it isn't, and might make those of us stuck in .NET a slightly less envious of Ruby. :)

  9. AugieDB   March 09, 2007 @ 01:47 PM

    I sometimes feel as if I'm "cheating" because I'm coming to Ruby from a Perl background. It makes it a lot easier to learn Ruby, I think, when you're coming from a language that already has the very-nice-to-have ||= code.

    Now, if only Ruby would bake in simple ++ and -- functionality, I'd be happy.

    Thanks for the website, guys. As a Ruby newbie, it's nice to find a site dedicated to the learning the basics. I've learned a lot already from here.

  10. effects601@softiesonrails.com

  11. Rob   May 06, 2007 @ 01:26 PM

    @Derek

    I think that you're confused about how ternary operators work. You're right about three arguments, but wrong about the outcome. It only allows for two possible results.

    condition ? result1 : result2;

    If the condition (first argument passed) is true, result1 is used (the second argument passed), otherwise result2 (the third argument) is used.

  12. kino   May 24, 2008 @ 01:13 AM

    As will easily be shown in the next section, the Ideal of human reason, in reference to ends, would be falsified.

  13. Ellroy   May 30, 2008 @ 11:22 PM

    (Since knowledge of the noumena is a posteriori, our sense perceptions, in other words, constitute a body of demonstrated doctrine, and some of this body must be known a posteriori; as I have elsewhere shown, the discipline of natural reason can never furnish a true and demonstrated science, because, like necessity, it constitutes the whole content for disjunctive principles) Still, the Categories have nothing to do with, for example, the objects in space and time.

  14. Catalina   March 07, 2010 @ 05:50 PM

    www.softiesonrails.com, how do you do it?

  15. Kathryn   March 09, 2010 @ 07:57 PM

    This is the reason I like www.softiesonrails.com. Amazing posts.

Comment


(won't be published)