Luau Switch Keyword

As a Roblox developer, it would be convenient to have access to a switch keyword like in a lot of other languages.

If Roblox is able to address this issue, it would improve my development experience by allowing me to keep my code neater and more compact.

Old syntax (cannot work)

Here is an example of the switch keyword vs without:

switch myVariable
	case "abc123":
		print("Value was abc123")
		break
	default:
		print("Value was something else")
end

if myVariable == "abc123" then
	print("Value was abc123")
else
	print("Value was something else")
end
switch myValue
	case nil:
		print("Value was nil, allow?")
		break
	case false:
		print("Value was false, error?")
		break
	default:
		print(myValue)
end

Latest syntax proposed (better described in my reply):

switch value
    for "a" do -- Case a
        -- Code
        -- No break, so fall through
    end
    for "b" do -- Case for b
        -- Code
        break -- No fall through, so a or b will run this code
    end
    for "a", "b", "c" do -- Case for a, b or c
        -- Code
        break
    end
    do -- Default case (which has no for statement and no values because it's what occurs when there isn't a value. You could have a for keyword before, however I think this makes more sense and would allow for more confident case value syntax)
        -- Code
    end
end
11 Likes

So I feel it’s important to note here that, typically, switch does not behave identically to a chain of else if statements.

If Roblox did add switch to Luau, I would hope it would behave with fall-throughs rather than being a syntactic sugar for elseif chains.

3 Likes

I had intended to include breaks in my examples as I like fall-throughs as well, but I didn’t for some reason so I’ve changed my example syntax to include them.

I don’t think a label system like that would work

switch value
    case a:b()
end

Is : used for a method call (case for if value is equal to the result of a:b()) or is : used for the end of the label so that if value is a then call b

Perhaps just omitting the : would resolve this ambiguity

switch value
    case "a"
        print"a"
        -- FALL THROUGH
    case "b"
        print"b"
        break
    default
        print"c"
end
3 Likes

What about scripts that use switch and case as identifiers? Making every keyword context-based is probably messy and confusing.

2 Likes

This was discussed with the addition of the continue keyword. I think that the benefits of having switch outweigh the usage of these identifiers becoming a little more confusing. Generally this would only be a problem if you’re scanning down a script quickly.

3 Likes

There would be additional ambiguity if case wasn’t disallowed as an identifier

switch value
    case "a"
        print"a"
        case"b" -- remember, this is a valid function call
        case("b") -- also ambigous
    case "c"
        print"c"
end
1 Like

This is true. Perhaps case could require ending with do/then?

switch variable
	case "a" do
		-- Stuff
		break
end

It would also need an end,

switch value
    case "a" do
        print"a"
        case"b" do -- do end creates a scope, but it seems ambiguous here
            print"b"
        end
end
switch value
    case "a" do
        print"a"
        case"b" do
            print"b"
        end
    end -- case scope ends here, ambiguity is resolved
end

Edit:
This would be really annoying when using multiple cases in a row

switch value
    case "a" case "b" case "c"
        print"a, b, or c"
end

would become

switch value
    case "a" do end case "b" do end case "c" do end
        print"a, b, or c"
end
1 Like

I’ve come up with the following “compromise” syntax for switches:

switch value
    for "a" do -- Case a
        -- Code
        -- No break, so fall through
    end
    for "b" do -- Case for b
        -- Code
        break -- No fall through, so a or b will run this code
    end
    for "a", "b", "c" do -- Case for a, b or c
        -- Code
        break
    end
    do -- Default case (which has no for statement and no values because it's what occurs when there isn't a value. You could have a for keyword before, however I think this makes more sense and would allow for more confident case value syntax)
        -- Code
    end
end

Essentially the switch clause requires an end. Inside of the switch clause sort of “mimic” for blocks are used. Values immediately before do can be separated with commas. Essentially this is a tuple. These act like blocks with fall throughs together, but in a much smaller form. This feels very lua-like imo, and I think this syntax would actually be easy to implement.

The “mimic” for blocks are possible to use within the switch case because they would occur within a switch case. They will consume the for keyword before a for loop would be implied.

The reason that switch value will not expect a function call is due to the end keyword. If this is difficult to implement for some reason or another, switch for value would solve this issue.

The reason for including the for keyword prior to case statements lies in the initial switch value statement. Value could be treated as a function, and the case value (e.g. “a”), the argument. The for keyword could be avoided by consuming the tokens that make up value however this would be pretty difficult to do, and honestly, I love the usage of for here.

The case statements look like a for loop, yet clearly aren’t at the same time due to the lack of the in keyword. You can read it as “for string “a”, string “b”, and string “c” do this” whereas for loops read like “for a, b and c in this iterator do this” so it reads nicely. It’s intuitive that break would be used here due to its similarity to for loops, and the switch statement’s usage in other languages. It just looks so much like lua, and I really like how it flows when writing out example code.

If anyone wants to point out any issues you see with this proposed syntax, or you have some comments on it you should definitely reply with your own suggestions because all of the prior syntax I’ve proposed (as discussed above) has been flawed in some way or another, and can’t really be used.

1 Like

The continue keyword was a special case, because it has very minimal cost (almost no engineering decisions to make because there’s an obvious way it should work), is immediately and fully understood by anyone who has programmed in another language, and has a very positive impact on a lot of code.

Don’t expect other significant changes to the language syntax.

1 Like

That’s definitely true and I definitely agree that it’s a special case, so I don’t have my hopes up too high for changes like this to be made.

I do think that this suggestion is possible to implement without issues, and could be done so in a performant way, but I think that there is a certain ambiguity to some syntaxes which could introduce issues. That’s why I’m attempting to come up with a syntax which covers as much ambiguity as possible without effecting usability, so the parser can be 100% confident without impacting performance.

The main situation where ambiguity could occur is in no parenthesis based function calls for sure. These calls are particularly hard to get around which is why keywords which would normally cause a syntax error must be used. This makes it very difficult to come up with a syntax that looks/reads/types nice and can be parsed without ambiguity or extra performance costs, so it’s definitely very hard for Roblox to confidently implement any syntax, hence why I feel that proposing and reworking a syntax like I am is necessary for my suggestion, and I feel that it’s the only way it makes sense for this suggestion.

Yes, it may be possible to introduce it in an unambiguous way with a clever enough formulation, but how much benefit actually is there to having a switch statement in Lua?

I would posit this: Python is one of the closest languages to Lua in usage feel, and it does not have a switch statement either. This is despite Python having very complex syntax too, so it’s not missing out of a fear of having too much syntax.

Many of the cases that would normally be covered by a switch in a language like C can more effectively be covered by a hashmap of handler functions in Lua.

3 Likes