Lua and Case Statement

Posted by Gore on Wed 04 Apr 2007 06:53 AM — 12 posts, 47,537 views.

#0
I know Lua does not have a case statement, so I tried looking up something that would be similar and I found this site: http://lua-users.org/wiki/SwitchStatement , and I tried looking at the examples but there's a few things I don't quite understand.

do
  local switch
  function sayit(letters)
    for _,v in ipairs{sayit} do
      switch = switch or {a = "aah", b = bee, c = "see", ..., z = "zee"}
      local s = switch[v] or "what?"
      print(s)
    end
  end
end
sayit{'h','e','l','l','o','?'}


What does the switch = switch or {a = "aah", b = bee, c = "see", ..., z = "zee"} line do? How does whether to do one, -or- the other?
USA #1
Well, for starters, it's important to point out that isn't actually Lua code, it's pseudo-code that is very close to Lua. E.g., the "..." should presumably be replaced with the whole alphabet.


Now, what the line is doing is simply creating the table called "switch" if it doesn't already exist. To create the table, it creates an index where the key is mapped to the thing to do. But this isn't actually doing anything, other than creating the index table. The next line, with switch[v], is where the table lookup is happening.

In this case, the "switch statement" (if one may call it that) is simply a mapping from string to string, saying what string to print for each input string.

Another option would be to map variable values to functions, but that's a little more complicated...
Australia Forum Administrator #2
Check out this post:

http://www.gammon.com.au/forum/bbshowpost.php?id=6219

It discusses the various ways you can do that in some depth.
Australia Forum Administrator #3
Quote:

do
local switch
function sayit(letters)
for _,v in ipairs{sayit} do
switch = switch or {a = "aah", b = bee, c = "see", ..., z = "zee"}
local s = switch[v] or "what?"
print(s)
end
end
end


That is actually pretty obscure code. I don't see why it couldn't be written:


do
  local switch =  {a = "aah", b = bee, c = "see", ..., z = "zee"}
  function sayit(letters)
    for _,v in ipairs{sayit} do
      local s = switch[v] or "what?"
      print(s)
    end
  end
end


Even then it doesn't really seem to work as intended, as it is switching on "sayit" and not its argument. Plus, he has put "sayit" into { } brackets, which turns it into a table with one element in it. That won't work either. Also, "bee" isn't quoted. It should read something like:


do
  local switch =  {a = "aah", b = "bee", c = "see", z = "zee"}
  function sayit(letters)
    for _,v in ipairs (letters) do 
      local s = switch [v] or "what?"
      print(s)
    end
  end
end

sayit {'a', 'b', 'c'}


Unfortunately, as an example of Lua code, it is riddled with bugs.

#4
local s = switch [v] or "what?"


What does that line signify? Why is the or in there?
USA #5
This is the line that actually does the switching. It scans through the switch variable defined above and will match the letter to the value. If not, a nil value is returned.

The or part is a bit odd, but standard Lua practice. When (foo or bar) is called and at least one of the values is non-boolean, the first value is always taken unless it is nil. If the first value is nil, then the second value is assigned. So in this example, if there is no valid data for the switch, a "what?" is used instead.
USA #6
The values don't have to be non-Boolean. If you have a = false or true, a is true. If you get a = false or false then a is false. But yes, it's a very common idiom for setting default values in case the value provided was nil.
USA #7
Well, if they are both boolean values, then the or is considered a boolean operator.

nil or false -> false
nil or true -> true
nil or 12 -> 12
12 or false -> 12
12 or true -> 12
false or 12 -> 12
true or 12 -> true
false or nil -> nil

So I guess if the first value is nil or false, then it's passed to the second value. Either way, in most languages you can't have an or in an assignment without the result being boolean.
Amended on Sat 07 Apr 2007 07:27 PM by Shaun Biggs
USA #8
Well, not really, it's just that most languages won't preserve the actual value. It's perfectly fine to do something like: var = thisIsAPointer || true; in which case it evaluates the whole as a boolean expression. But yeah, that'd be a little weird...
USA #9
You can do that, but it is considered horrific by programming standards. With Lua, the nil test is perfectly acceptable. This drives a few people nuts, but I love it.
Australia Forum Administrator #10
Quote:

local s = switch [v] or "what?"

What does that line signify? Why is the or in there?


To put it another way ...

This is exactly equivalent to, but shorter than:


local s = switch [v] -- look up item in table

if s == nil then
  s = "what?"
end -- if


Basically it works because variables in Lua are untyped. That is, the value has a type, but the variable itself can hold any type.

If you take short-circuit boolean expression: this or that

Then the result is "this", but if "this" is considered false (that is, the value 'false' or 'nil' (without the quotes)), then the expression evaluates to "that" - whatever the type of "that" is - including nil.


USA #11
Quote:
You can do that, but it is considered horrific by programming standards
Well, that depends on who you ask. I think it obscures what is going on, but sometimes it is useful if you want to check if at least one pointer is non-null. Also, it can be useful if you want to check if one of several numbers is non-zero.

The thing to remember is that in C++ boolean expressions are boolean whereas in Lua there is the "this or that" situation Nick described.