Lua doesn’t have true ternary operator but there is a way to mimic the behavior. This is one of the biggest issues people who aren’t used to Lua have when reading Lua code. For the most part Lua is simple and straight forward to understand. Assuming a blocky and easy to understand style is used. However, the pseudo ternary is often used and trips up people. So let’s look at it in some detail.

The core of a ternary is an `if ... else` statement. In Lua, we can mimic this using `and ... or` with the evaluated statement. What we end of is `if` true then use the code path after `and` or `if` false use the code path after the `or`. Let’s look at a simple example.

``````if a == nil then
b
else
c
end
``````

This is the equivalent to:

``````a == nil and b or c
``````

Let’s look at more complex logic.

``````if a ~= nil and (1 < 5) then
b
else
c
end
``````

We can do the same thing with the `and ... or` syntax. We just need to use parenthesis like we would with an `if` statement to separate what applies to which part of the statement

``````(a ~= nil and (1 < 2 or 4-2 > 5)) and b or c
``````

We do need to be very careful with the separation. For this to work it always has to be `(statement) and (statement) or (statement)`. Notice the `and` and `or` cannot be within parentheses. Here is a bad example that doesn’t work like you’d expect.

``````a ~= nil and (b or c) .. a
``````

In this situation we’d end up with `b` concatenated with `a` which is expected. However, if `a == nil`, then we would end up with `false`. This statement does not have a proper `or` for the `false` code path of the logic. Since there is no code path Lua returns `false` for in this situation. The proper way to handle sticking a tailing statement to the ternary is to put the entire operation into parentheses.

``````(a ~= nil and b or c) .. a
``````

Regardless of which branch is chosen we’ll always get the variable concatenated with `a`.

Now let’s look at complex components components.

``````a ~= nil and (b .. c .. a) or (a .. c .. b)
a == nil and (b .. c .. a) or (a .. c .. b)
``````

This goes back to proper use of parentheses. We have the decision, the `and` and `or` outside of any parentheses and the code paths themselves within to properly contain the logic.

Let’s put together some samples we can run to really demonstrate everything that’s been covered.

``````local a = "123"
local b = "xyz"
local c = "test"

print("Simple if")
if a == nil then
print("", b)
else
print("", c)
end
print("Equivalent simple ternary")
print("", a == nil and b or c)

print("Complex if")
if a ~= nil and (1 < 2 or 4-2 > 5) then
print("", b)
else
print("", c)
end
print("Equivalent complex ternary")
print("", (a ~= nil and (1 < 2 or 4-2 > 5)) and b or c)

print("", a ~= nil and (b or c) .. a)
print("", a == nil and (b or c) .. a)
print("Proper ternary")
print("", (a ~= nil and b or c) .. a)
print("", (a == nil and b or c) .. a)

print("Complex ternary")
print("", a ~= nil and (b .. c .. a) or (a .. c .. b))
print("", a == nil and (b .. c .. a) or (a .. c .. b))
``````

Now for the output

``````Simple if
test
Equivalent simple ternary
test
Complex if
xyz
Equivalent complex ternary
xyz
xyz123
false
Proper ternary
xyz123
test123
Complex ternary
xyztest123
123testxyz
``````

We should keep looking at this a bit further. In the above examples only variables were used and they were all run though a print statement. Ternary operations should be small and will typically only use variables. Such as using it for assignment. However, functions can be run in the `ture` and `false` branches and care needs to be taken.

Let’s look at an example with two functions.

``````print("Functions 1")

function b_func()
print("b_func", b)
end

function c_func()
print("c_func", c)
end

print("", true and b_func() or c_func())
``````

You might think only function `b_func` would run but that’s not what happens. `b_func` has no explicit return so implicitly it returns `nil`, which evolutes to false. `true` run the `true` branch (`b_func`), but since that branch returns `nil`/`false` it will then continue on and run the `false` branch (`c_func`). So we’ll end up with this output:

``````Functions 1
b_func	xyz
c_func	test
nil
``````

Both functions ran which is not at all what we’d want to happen. Also notice that since `c_func` also don’t have a return it returned `nil` and since it’s inside of a `print` statement `nil` is printed.

This can cause problems if you’re trying to run a function that either doesn’t have a return value or if it returns `nil`/`false` and you don’t care about the return. The `false` branch (`c_func`) will only run if the `true` branch (`b_func`) returns `true`.

This goes back to the fact this is not a true ternary but an evolution!

If we change `b_func` to return true like so.

``````function b_func()
print("b_func", b)
return true
end
``````

Then run it again we’ll get this output.

``````Functions 1
b_func	xyz
true
``````

This is what we want to happen with only `b_func` running. We still see `true` printed which is the return of the function because we’re running the return value through `print`.

If you’re working with functions you need to be very careful with this pattern otherwise more than you expect might run. My advise is if you’re calling functions don’t use this pseudo ternary and instead use a true `if` block. Only use this for variable assignment.

However, even with variable assignment you need to be careful with the `true` branch.

``````e = nil
g = true and e or c
``````

What do you think g will be, `nil` or `test` (`c`)? If you guessed `test` (`c`) you’re right. Again this is an evaluation. Our expression is `true`, go to the `true` (`and`) branch. That branch if `false` so evaluate the `false` (`or`) branch. Since it’s an or where either `e` or `c` for the evaluation then `c` will run whenever after `e` if it is `false`.

The next question is how to assign `nil` in the `true` branch. As far as I’m aware you can’t. So, use an `if` statement if you need `nil` assignment. It’s imperative that you are sure variable used for assignment with this ternary pattern will never be `nil` and any functions will either return `true` or a value otherwise this won’t work like you expect.

Hopefully this makes ternaries logic can be used in Lua clear to everyone.