hisham hm

Lua’s and-or as a ternary operator

Lua is a nice programming language, which allows for readable and concise code. One of my favorite idioms in the language is this:

x = a and b or c

which usually works like the C ternary operator, “a ? b : c”, but in a more readable fashion. This works in Lua because the “and” and “or” operators return their matching value when they get a “true” value (anything other than false and nil).

One thing to keep in mind though, is that this is really “and and b or c” and not “a then b else c”. There’s one big difference: when you want to have nil or false in your “then” value.

Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> = true and 10 or 20
10
> = false and 10 or 20
20
> = true and nil or 20
20

An ugly alternative is to do “not a and c or b”, like this:

> = not true and 20 or 10
10
> = not false and 20 or 10
20
> = not true and 20 or nil
nil

But at this point it’s better just to use an “if” statement. (This hack works around the then-as-nil case, but not else-as-nil, of course.)

So, keep in mind that you should use the “a and b or c” construct as if-then-else only if you know that your “b” value is not nil or false.

It’s better, however, to use this construct for what it is. This behavior is not flawed, it is just different, and it has its own uses. For example, it is very useful to check if a table exists:

x = tbl and tbl.key

And to define fallback values:

x = tbl and tbl.key or "missing!"

Note that the above line reads naturally, and you wouldn’t be able to do that with one “?:” operator in C.


  1. Senthil

    Thursday, May 5, 2011 - 01:29:49

    In Python, following works as well :

    a if else b

    For example:

    >>> a=’a’
    >>> b=’b’
    >>> v=a if True else b
    >>> v
    ‘a’
    >>> v=a if False else b
    >>> v
    ‘b’

  2. Chad Dumler-Montplaisir

    Thursday, May 5, 2011 - 05:02:02

    If I might add, you’re confusing conditional operatiors with functional flow operators. AND, OR, NOT are functional, meaning they execute the statement and return a value, which allows the program to flow based on the value. The AND operator executes the first operation and executes the second operation if the first value is in the class of truth. This is often used as a guard operation:

    record = Table.find(some_id) and record.destroy # only try to destroy the record if it exists

    The OR operator is the opposite. It executes the first operation and if it’s value is in the class of falsehood it executes the second operation:

    record = Table.find(some_id) or Table.new_record # Find record or if not found return a blank one

    Put together does allow concise flow, such as :

    # Associate with given ID or associate with a new record
    record = Table.find(some_id)
    record = record and record.associate(other_record) or Table.new.associate(other_record)
    # Note, either way record will be valid after execution.

  3. hisham

    Thursday, May 5, 2011 - 05:32:42

    Thanks for the feedback! I do realize this and tried to point that out near the end, but I think you said it in a clearer way.

    The goal of this post was very much to point out the differences one may run into when one uses the and-or construct as if it was a ternary conditional operator.

  4. Laurens Van Houtven

    Thursday, May 5, 2011 - 16:14:15

    A “real” ternary expression, in the form of “a if cond else b”, was added to Python almost five years ago. If you’re still using Python versions that old, you must be on RHEL or something. Consider upgrading.

Add comment

Fill out the form below to add your own comments.

CAPTCHA imageReload imageAudible version of CAPTCHA-image