Groovy snippets

Jul 20

I like the simplicity of languages like Ruby and JavaScript. In both of these languages, you can do something similar to:

foo = bar || "default"

This actually assigns either bar (if it is truthy), or "default" to foo.

Sadly, with Java and Groovy, foo will actually have either true or false as a value. Behold, there is a way to do the same thing with Groovy:

foo = bar ?: "default"

It’s kind of a play on the ternary operator.

This means I can reduce this code

User currentUser = User.findByName(user)

if (!currentUser) {
    currentUser = new User(name: user)
    currentUser.save()
}

session.user = currentUser

to the one liner:

session.user = User.findByName(user) ?: new User(name: user).save()
Trackbacks

Use the following link to trackback from your own site:
http://chrisbroadfoot.id.au/trackbacks?article_id=groovy-snippets&day=20&month=07&year=2008

Comments

Leave a response

  1. Avatar
    1. Matt Ryall about 1 hour later:

    Nice tip! Note, your final one-liner only works if User.save() returns the user, which I presume is the case. :)

    Perl has a handy extension on the ‘or’ operator (||) that lets you simplify the common case of a default value for an argument. So instead of the following JS:

    function foo(arg) {
        arg = arg || "some default";
        // ... use arg ...
    }
    

    You can use Perl’s ||= operator:

    sub foo {
        my ($arg) = @_;
        $arg ||= "some default";
    }
    

    Of course, the down-side of the underlying ‘or’ operator in a dynamic language is that values like the empty string (“”) or zero (“0”) are treated as false. So passing a zero to either of the above functions would use the default value instead.

    To avoid this, Perl 6 is introducing another operator (typical Perl!) to only evaluate the RHS if the argument is undefined:

    sub foo_perl6 {
        my ($arg) = @_;
        $arg //= "some default";
    }
    

    Pretty useful, I’d say. Not correctly distinguishing between zero and false is a common problem in JS code.

  2. Avatar
    2. Chris Broadfoot about 14 hours later:

    Nice.

    I suppose Ruby borrowed from Perl (among other things) the ||= “caching” assignment operator. It would be awesome to have this in Groovy, too.

    0 and "" are actually treated as truthy in Ruby, which is kinda cool.

    One thing that I would like to see in Groovy is the opposite of ?:

    foo = boolean && "value if boolean is truthy"
    

    But even the ?: shortcut is really useful.

  3. Avatar
    3. JudoCoder 5 days later:

    The (?:) operator in Groovy is called the “Elvis operator”. It returns the second argument if the first argument is false or null. C# 2.0 introduced the Null Coalescing Operator (??) which is similar: it returns the second argument is the first argument is null.

    Groovy also has the Safe Navigation Operator (?.). Foo?.Bar?.Zot will return null if either Foo or Bar are null, instead of throwing an exception.

    But you can reduce your example code…

    User currentUser = User.findByName(user)
    
    if (!currentUser) {
        currentUser = new User(name: user)
        currentUser.save()
    }
    
    session.user = currentUser`
    

    to one line of code without using the Elvis operator! It’s simply…

    if (!(session.user = User.findByName(user))) {session.user = new User(name: user).save()}
    

    Il Papa

Leave a comment…