# Ternary Operator

## The Problem

There are times when it would be preferable to use an if-then-else conditional statement as an expression. Consider this code:

```if x < 0 then
print('x is negative')
else
print('x is non-negative')
end
```

Stylistically, repetition like `print('x is ' ...)` is to be avoided ([DRY]), particularly if this repeated code were instead something much more complicated. One way to resolve that is with a variable:

```local sign
if x < 0 then
sign = 'negative'
else
sign = 'non-negative'
end
print('x is ' .. sign)
```

But now we've introduced new style problems: although the naming of a value (`sign`) can be useful for documentation purposes, the name is repeated in four locations, its scope undesirably extends beyond the `print` statement, and the length and complexity of the code is arguably increased. What we may really want to do is bring the if-then-else into the expression, like this:

```local sign = if x < 0 then 'negative' else 'non-negative' end
print('x is ' .. sign)

-- or just this...
print('x is ' .. if x < 0 then 'negative' else 'non-negative' end)
```

where the form `if a then b else c end` would be an expression that evaluates to `b` when `a` is true and otherwise evaluates to `c`. However, this syntax is not supported in Lua. Some languages do support this construct directly: it is called a conditional ternary operator [1]. It is "ternary" because there are three operands: `a`, `b`, and `c`. For example, in the C language, the ternary operator is written like

```sign = (x < 0) ? "negative" : "non-negative";
```

Ternary operations can also be chained, analogous to "`elseif`" clauses:

```x = (a < amin) ? amin : (a > amax) ? amax : a;
```

Here, the ternary operator has right-associativity, which means the parenthesis are implied according to the first (not second) line below:

```x = (a < amin) ? amin : ((a > amax) ? amax : a);
x = ((a < amin) ? amin : (a > amax)) ? amax : a;
```

This is analogous to how the following Lua if-then-else statements are equivalent:

```if a < amin then
x = amin
elseif a > amax then
x = amax
else
x = a
end
```

```if a < amin then
x = amin
else
if a > amax then
x = amax
else
x = a
end
end
```

Even though Lua lacks ternary operators explicitly, there are ways to closely approximate it, as described below.

## Standard solution: and/or

A frequently used and highly recommend solution is to combine the `and` and `or` binary operators in a way that closely approximates the ternary operator:

```x = a and b or c
x = a and b or c and d or e
```

See the book ProgrammingInLua? or ExpressionsTutorial for details on the special properties of these binary operators that allow them to work this way.

```print('x is ' .. (x < 0 and 'negative' or 'non-negative'))  -- this works!
```

The main caveat is that if `a` or `c` evaluates to true while `b` or `d` respectively evaluate to false, then this expression will not behave exactly like the ternary operator. Here, "evaluate to false" means that the value is either `false` or `nil`, and "evaluate to true" means not evaluate to false. In the first line above, `a and b or c` is interpreted as `(a and b) or c` (because `and` has higher precedence than `or`), and if `a` evaluates to true, then the expression becomes `b or c`, and if `b` evaluates to false, then the expression becomes `c` (not `b` as you might want).

Often, as in the case of our original example, the second operand of the tertiary operator can never evaluate to false, so you are free to use this idiom, but beware of the caveat. If the `b` will evaluate to false, change the `a` so that it evaluates exactly opposite and therefore swaps `b` and `c`

```print((x < 0 and false or true))  -- this fails!
```

```print((x >= 0 and true or false))  -- this works!
```

## Anonymous functions/closures

You can insert arbitrary statements inside expressions via an anonymous function (or closure), and this includes if-then-else statements:

```print('x is ' .. (function() if x < 0 then return 'negative' else return 'non-negative' end end)())
```

A main downside is that this creates an anonymous closure on every execution, which may reduce performance in a tight loop. Also, anonymous function syntax is a bit verbose in Lua (as detailed in ShortAnonymousFunctions).

## Functional-if

One can also write `if` as a function:

```function fif(condition, if_true, if_false)
if condition then return if_true else return if_false end
end
print( fif(condition, a, b) )
```

but this does not have the advantage of short-circuiting unless the conditions are expressed as anonymous closures for delayed evaluation:

```function fif(condition, if_true, if_false)
if condition then return if_true() else return if_false() end
end
local x = fif(condition, function() return a end, function() return b end)
print(x)  --> false
```

## Boxing/unboxing

To avoid the above problems with nil's, you may "box" those values in some expression that is never nil. Unfortunately, the boxing imposes an overhead.

```local condition, a, b = true, false, true
local x = (condition and {a} or {b})[1]
print(x)  --> false
```

Here's a similar solution but using functions:

```local False = {}
local Nil = {}
local function bwrap(o)
return o == nil and Nil or o == false and False or o
end
local function bunwrap(o)
if o == Nil then return nil
elseif o == False then return false
else return o end
end

local x = bunwrap(condition and bwrap(a) or b)
print(x)  --> false
```

## Stack

Here's an interesting (and rarely used) stack-like approach, with stack of size 1:

```local save, restore do
local o_saved
save = function(o) o_saved = o; return true end
restore = function() return o_saved end
end

local x = (condition and save(a) or save(b)) and restore()
print(x)  --> false
```

## Syntax Extensions

The following are some proposals for extending Lua syntax to support the ternary operator more directly.

## Simple syntax extension

Perhaps the most Lua-ish syntax extension, introducing no new keywords, and preserving the current conditional syntax as much as possible, is something like these:

```x = if a then b elseif c then d else e end
x = (if a then b elseif c then d else e end)
x = (a then b elseif c then d else e)
```

## Syntax extension: then/or keywords

Some people propose syntaxes like these:

```x = a then b else c
x = a then b or c
```

but they cause ambiguities when used inside conditional statements:

```if a() then b() else c() then d() end
```

## Syntax extension: Pythonic "x if y else z"

There are syntactic advantages to having the condition as the middle argument of the conditional ternary operator, as John Backus pointed out many years ago:

`x = a when a < b else b`

gives `x` the value of `a` if `c` is the first condition to be true. This could be accomplished with the current Lua syntax if `when` were defined as `and` but with arguments interchanged (so with lazy evaluation of its first argument). Unfortunately this is not as straightforward to implement as might at first appear, because it means holding over the evaluation of an expression until a succeeding expression has been evaluated. This is what was done for Python's new conditional expressions [2]. --Anonymous

## MetaLua

MetaLua includes an example ([ifexpr.mlua]) for adding this syntax:

```local foo = if bar then 1 else 2
```

--DavidManura, et al.