Inline conditions in Lua (a == b ? "yes" : "no")?
Asked Answered
S

7

156

Is there anyway to use inline conditions in Lua?

Such as:

print("blah: " .. (a == true ? "blah" : "nahblah"))
Si answered 2/4, 2011 at 20:56 Comment(1)
There is a nice article on lua-users wiki about ternary operator, together with problem explanation and several solutions.Bayreuth
O
222

Sure:

print("blah: " .. (a and "blah" or "nahblah"))
Oleneolenka answered 2/4, 2011 at 20:59 Comment(7)
+1 for the answer. However I don't think this is strictly true -- I don't use LUA -- but I think it shares a "flaw" with this approach over a ternary operator in other languages. Imagine: (cond and false-value or x) That will result in the x in all cases.Foyer
wouldn't that also print the value of A as well?Irrevocable
@glowcoder No. "The conjunction operator (and) returns its first argument if this value is false or nil; otherwise, and returns its second argument. The disjunction operator (or) returns its first argument if this value is different from nil and false; otherwise, or returns its second argument. Both and and or use short-cut evaluation, that is, the second operand is evaluated only if necessary" -- from lua.org/manual/5.0/manual.htmlFoyer
@pst very cool. I'll be 100% honest and say the most Lua I've ever done consists of rummaging through some WoW addons. Thanks for the detailed explanation (even if it is just copy/paste) :)Irrevocable
@pst is correct that if the intent is that a and false or true is not going to give the same answer as not a. This idiom is usually used for cases where the desired value if a is true cannot be false or nil.Omnidirectional
If you are using this form with variables, you probably assume that the second variable is non-false, which means you should write a and assert(b) or c.Schaffel
@Foyer I completely agree with your point, but it's "Lua", not "LUA" - it's not an acronym, it's the Portuguese word for moon.Pincers
T
51

If the a and t or f doesn't work for you, you can always just create a function:

function ternary ( cond , T , F )
    if cond then return T else return F end
end

print("blah: " .. ternary(a == true ,"blah" ,"nahblah"))

of course, then you have the draw back that T and F are always evaluated.... to get around that you need to provide functions to your ternary function, and that can get unwieldy:

function ternary ( cond , T , F , ...)
    if cond then return T(...) else return F(...) end
end

print("blah: " .. ternary(a == true ,function() return "blah" end ,function() return "nahblah" end))
Taut answered 3/4, 2011 at 12:29 Comment(4)
I think this is the most useful for boolean variablesConvolution
This answer is actually better than the top answer because it works for booleans as well.Maddi
I think a more common edge case that this solution accommodates is when t is nil.Toluate
great! best awnser! works great with any type... and ternary inside ternary...nice work man! thanksLoiseloiter
T
20

You can usually do:

condition and ifTrue or ifFalse

but this isn't necessarily the best way to do it. The major reason why is because if ifTrue is a falsy value (some of the time), ifFalse will evaluate even if condition is a truthy value. One way to do it simply without much extra work is:

(condition and {ifTrue} or {ifFalse})[1]

which has the advantage of not only being an expression and not being subject to the problem of ifTrue being falsy which means it can handle all cases, but also has the advantage of short-circuiting (not evaluating the other expression). No need for extra functions or messing with complex aspects of Lua.

Tove answered 26/4, 2022 at 23:23 Comment(1)
Damn, I thought this was wrong, per #5526317 BUT i tested it in the demo lua.org/cgi-bin/demo and indeed you have to check if the middle expression is falsy...Avert
H
2

Although this question is fairly very old, I thought it would be fair to suggest another alternative that syntactically appears very similar to that of the ternary operator.

Add this:

function register(...)
    local args = {...}
    for i = 1, select('#', ...) do
        debug.setmetatable(args[i], {
            __call = function(condition, valueOnTrue, valueOnFalse)
                if condition then
                    return valueOnTrue
                else
                    return valueOnFalse
                end
            end
        })
    end
end

-- Register the required types (nil, boolean, number, string)
register(nil, true, 0, '')

And then use it like this:

print((true)  (false, true)) -- Prints 'false'
print((false) (false, true)) -- Prints 'true'
print((nil)   (true, false)) -- Prints 'false'
print((0)     (true, false)) -- Prints 'true'
print(('')    (true, false)) -- Prints 'true'

Note: For tables, however, you cannot use them directly with the above method. This is because each and every table has it's own independent metatable and Lua does not allow you to modify all tables at once.

In our case, an easy solution would be to convert the table into a boolean using the not not trick:

print((not not {}) (true, false)) -- Prints 'true'
Hoboken answered 1/4, 2021 at 10:1 Comment(0)
T
1

You could just write the if statement in one line, it is no shorthand, inline or ternary operator stuff tho.

if (dummy) then
    print("dummy is true")
end

is equal too

if (dummy) then print("dummy is true") end
Thorman answered 9/3, 2022 at 20:52 Comment(0)
G
1

Lua is deliberately lightweight so it does not have a ternary operator.

There are a couple of ways to get past this including using the and-or idiom. But I think that is bad for multiple reasons. Mainly because beginners don't understand it though.

I suggest using a function:

local function choice(c, t, f)
    return c and t or f
end

local s = choice(2 % 2 == 0, "even", "odd")
Gaza answered 15/10, 2023 at 8:36 Comment(2)
This has the same flaw as the and-or idiom -- if the t is falsy it returns f even when c is truthyAvert
You are 100% right. I said it was bad for multiple reasons. The main one being that it was confusing for beginners. There is a much better function that can be written but the point was that as the ternary operator does not exist people use "tricks" which are not obvious to the beginner. You can wrap it in a function that conveys the meaning better. Ideally, you would write tests to document what the function does and as you have pointed out this would soon reveal the underlying problem with the and-or idiom.Gaza
C
0

Have fun :D

local n = 12
do
    local x = (n>15)
            and print(">15")
            or n>13
            and print(">13")
            or n>5
            and print(">5")
end
Choppy answered 3/2, 2022 at 10:17 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.