Встроенные условия в Lua (a == b? "Yes": "no")?

Есть ли способ использовать встроенные условия в Lua?

Такие как:

print("blah: " .. (a == true ? "blah" : "nahblah"))

8 ответов

Решение

Конечно:

print("blah: " .. (a and "blah" or "nahblah"))

Если a and t or f не работает для вас, вы всегда можете просто создать функцию:

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

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

конечно, у вас есть недостаток, что T и F всегда вычисляются.... чтобы обойти это, вам нужно предоставить функции для вашей троичной функции, и это может стать громоздким:

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))

Обычно вы можете сделать:

      condition and ifTrue or ifFalse

но это не обязательно лучший способ сделать это. Основная причина в том, что если это ложное значение (иногда), ifFalseбудет оценивать, даже если conditionявляется истинным значением. Один из способов сделать это просто без дополнительной работы:

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

преимущество которого состоит не только в том, что оно является выражением и не связано с проблемой ifTrueбыть ложным, что означает, что он может обрабатывать все случаи, но также имеет преимущество короткого замыкания (без оценки другого выражения). Нет необходимости в дополнительных функциях или возиться со сложными аспектами Lua.

На liki-users wiki есть хорошая статья о троичном операторе, вместе с объяснением проблемы и несколькими решениями.

Хотя этот вопрос довольно старый, я подумал, что было бы справедливо предложить другую альтернативу, которая синтаксически выглядит очень похожей на таковую тернарного оператора.

Добавь это:

      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, '')

А затем используйте это так:

      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'

Примечание. Для таблиц, однако, вы не можете использовать их напрямую с помощью вышеуказанного метода. Это связано с тем, что каждая таблица имеет свою собственную независимую метатаблицу, а Lua не позволяет вам изменять все таблицы одновременно.

В нашем случае простым решением было бы преобразовать таблицу в логическое значение с помощью not not обманывать:

       print((not not {}) (true, false)) -- Prints 'true'

Lua намеренно облегчен, поэтому в нем нет тернарного оператора.

Есть несколько способов обойти это, включая использование идиомы «и/или». Но я думаю, что это плохо по нескольким причинам. В основном потому, что новички этого не понимают.

Я предлагаю использовать функцию:

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

local s = choice(2 % 2 == 0, "even", "odd")

Вы можете просто написать оператор if в одной строке, это не стенографический, встроенный или тернарный оператор.

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

тоже равно

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

Веселись :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
Другие вопросы по тегам