Using logical operators with expressions with multiple return values in lua

245 Views Asked by At

I'd like to do something like:

s,e = string.find(str, pattern1) or string.find(str, pattern2)

(because lua patterns don't have the equivalent of a regex |)

But this gives me nil for e even if one of the patterns matches.

How can I get both return values from the first function call to match?

2

There are 2 best solutions below

0
Piglet On BEST ANSWER

Both of your function calls are neither the only nor the last one in a list of expressions. Hence their list of return values is adjusted to 1 value.

See https://www.lua.org/manual/5.4/manual.html#3.4

hence

s,e = string.find(str, pattern1) or string.find(str, pattern2)

is more or less equivalent to

do
  local v1 = string.find(str, pattern1)
  if v1 then
    s, e = v1, nil
  else
    local v2 = string.find(str, pattern2)
    if v2 then
      s, e = v2, nil
    else
     s, e = nil, nil
    end
  end
end

Assuming the first pattern matches, then v1 is a true value. The or statement is being short-circuited so you assign

s, e = v1, nil

If the first pattern does not match the second string.find is called. If there's a match it's return value is a true value

s, e = nil or v2, nil

If the first pattern does not match and the second does not match you assign

s, e = nil, nil

You need to handle both string.find calls separately in order to not lose any return values.

local v1, v2 = string.find(str, pattern1)
if not v1 then
  v1, v2 = string.find(str, pattern2)
end
s, e = v1, v2
0
Jasmijn On

Lua lists are fragile, when used as an expression outside of very specific context (most importantly, if they're assigned to multiple names or as the last argument to a function), they devolve into their first value. To get the desired behaviour, you need to make sure to store all values. For example:

local s1, e1 = string.find(str, pattern1)
if s1 then
    s, e = s1, e1
else
    s, e = string.find(str, pattern2)
end