SegFault
SegFault

Reputation: 2546

Lua conditionals on nil types

Question(s)

In Lua:

local a = b or 0
local a = b and 1 or 0

Where b can be of any type.

What are the differences in between the lines of code? And in what cases would I use one or the other?


Context

I have to port existing Lua code to another service and I ran into a problem understanding why in some parts of the code (I'm not a Lua developer), a variable gets assigned to one and in other parts of the code, a variable gets assigned to another. The variable on the right hand side is an input parameter and I have no way of knowing the intended type.


What I have tried

I looked online for Lua documentation on this and I couldn't find any clear answers on this. I ran my own test:

local a1;
print(type(a1))               -- nil
local b1 = a1 or 0            
print(b1 .. " " .. type(b1))  -- 0 number
local c1 = a1 and 1 or 0
print(c1 .. " " .. type(c1))  -- 0 number

local a2 = 5
print(type(a2))               -- number
local b2 = a2 or 0          
print(b2 .. " " .. type(b2))  -- 5 number
local c2 = a2 and 1 or 0
print(c2 .. " " .. type(c2))  -- 1 number

local a3 = 0
print(type(a3))               -- number
local b3 = a3 or 0          
print(b3 .. " " .. type(b3))  -- 0 number
local c3 = a3 and 1 or 0
print(c3 .. " " .. type(c3))  -- 1 number

local a4 = false
print(type(a4))               -- boolean
local b4 = a4 or 0
print(b4 .. " " .. type(b4))  -- 0 number
local c4 = a4 and 1 or 0
print(c4 .. " " .. type(c4))  -- 0 number

local a5 = true
print(type(a5))               -- boolean
local b5 = a5 or 0
print(b5 .. " " .. type(b5))  -- error, concatenating boolean to string
local c5 = a5 and 1 or 0
print(c5 .. " " .. type(c5))  -- 1 number

local a6 = "str"
print(type(a6))               -- string
local b6 = a6 or 0
print(b6 .. " " .. type(b6))  -- str string
local c6 = a6 and 1 or 0
print(c6 .. " " .. type(c6))  -- 1 number

local a7 = ""
print(type(a7))               -- string
local b7 = a7 or 0
print(b7 .. " " .. type(b7))  --  string
local c7 = a7 and 1 or 0
print(c7 .. " " .. type(c7))  -- 1 number

It seems to me that the only use case for the line of code with the and conditional is when b is of boolean or nil type and a should result in 0 when b is nil or false and 1 when b is true.

Upvotes: 4

Views: 2617

Answers (1)

Tom Blodget
Tom Blodget

Reputation: 20772

In Lua, these are selection operators, with short-circuit evaluation.

false and nil are "falsey"; Any other value is "truthy." Except for "falsey", the operand types don't matter and the resulting type isn't necessarily "boolean".

  • or selects (returns) the first truthy operand.

  • and selects the first operand if it is falsey, otherwise the second operand. It has a higher precedence than or.

This leads to several idioms:

b or 0 -- default to 0
t = t or {} -- existing or new, empty table
b and 1 or 0 -- coerce to 1, defaulting to 0

The difference between your two examples, is the second coerces to 1, while the first lets a "truthy" b be.

Upvotes: 6

Related Questions