Lua is very flexible and very fun to hack! With a different approach [0], you can get a switch on tag that feels more like a "standard" switch statement, eg.:
result = switch(shape) {
rectangle = function(r)
return "a rectangle with width " .. r.width
end,
function(s)
return "an unknown shape"
end
}
Can't easily get rid of the pesky functions, though.
(Implicitly) using [1] instead of [false] as a default is less typing for sure (but maybe a bit more confusing?).
Also, objects being switched on really have to be tables in my version anyway (since overriding __call for builtin types seems harsh to me), so having a tag field right in them as opposed to creating a metatable should be more efficient.
For my version I'll add a value-weak map of metatables to dedup them, should work as well.
In terms of functions, yeah, I don't think you can get rid of them, but (in the example) you can avoid (r) and (s) params if you assume that the functions lexically close over shape.
I found it nice how it's possible to emulate switches in Lua with so little code, without the result looking too ugly. You may find this pattern useful. That's it.
The catch is that, unlike with normal switches or with a series of "if"s, there's a whole bunch of indirection added via functions, so it's not very efficient.
Perhaps LuaJIT can inline these functions, but I haven't tested it.
reply