Switch statements for LuaU

As a Roblox developer, it is currently too hard to manage spaghetti code with many if/else statements, and there are solutions within the C language and C++ languages for this very thing. I would like to request Switch statements.

If Roblox is able to address this issue, it would improve my development experience because I could cut out If/Else spaghetti, instead having one big switch statement that can check a bunch of stuff.

References for switch statements:

9 Likes

New language features come with a pretty big price, we need use cases in order to help estimate the benefits of that cost. Can you provide use cases where an if/else is substantially less readable than switch/case?

For example, something like this:

if color == "red" then
  -- do stuff
elseif color == "blue" then
  -- do stuff
elseif color == "green" then
  -- do stuff
end

…is not really much less readable than:

switch (color) {
  case "red":
    // do stuff
  case "green":
    // do stuff
  case "blue":
    // do stuff
}

…and also adds an extra level of indentation and loss of control in being able to add extra conditionals.

15 Likes

I find switch cases to be far more readable than

if x then

elseif y then

elseif z then

end

I also find that it would be helpful to have something that doesn’t break at the first true statement. Switch cases will check everything provided, if/else does not. A practical use case would be to check something like an achievement system. I have 5 types of data I need to check for and if/else will only check for 1. I’d like to be able to avoid

if datatype then

end if otherDataype then

end -- repeat 5 times

If there is a better way than switch cases (or if I am mistaken about some of the logic here), let me know, but I feel like switch cases are far more readable and more practical than the above.

Small edit, I made it end if instead of elseif because of the “break at first true condition” thing above

1 Like

This would also break tons of code bases if switch and case become reserved keywords.

2 Likes

You shouldn’t worry too much about that–we already contextually parse specific identifiers as keywords–continue being the notable example, where you can name a variable continue and use it everywhere you could’ve used a normal variable, but we understand that it can be its own statement as well.

6 Likes

Yes, this exactly!

Just because other languages have a feature doesn’t mean every new language needs to be a collection of them + more.

Languages are tools to accomplish a goal - and if/else definitely allows you to do more than anything you need. Bloated languages can be less approachable for newer / younger users, and also lead into pitfalls when you don’t remember minor edge cases (for example, Lua arrays starting at 1)

8 Likes

I literally just learnt what a switch statement was in computer science today and im surprised i have never heard of it before. This would be pretty useful if it was implemented

4 Likes

I would absolutely love for this to be a feature. The difference in readability while not majorly different, I do think that ‘case’ is a lot cleaner. Especially when your game has a huge ton of if/elseif everywhere and it gets kind of cluttered.

There may be need for extra indentation, but that is a cost I’m willing to pay. I also think it’d just be nice to have different ways to handle logic cases. I’d personally use this if it became a feature.

5 Likes

I’ll add to this with a specific example using your provided code

Say red and blue are true, but not green.
You’d have to check for that by doing this:

if color == "Red" then

end if color == "Green" then

end if color == "Blue" then

end

Versus

switch (color) {
  case "red":
    // do stuff
  case "green":
    // do stuff
  case "blue":
    // do stuff
}

The switch/case will execute both red and blue, while ignoring green

2 Likes

Can you provide a code snippet example of what you mean? What specific set of if statements did you use that led you to want this? I’d like to review your code to understand what you’ve written. This way, I can explore potential alternatives to avoid the need for a large number of if statements.

2 Likes

Sure thing. I really can’t share specifics due to NDA stuff but I can give you sort of a mockup

I’m working on an achievement system where there are a lot of kinds of requirements and unlock conditions. With if/else, I have to use

if achievement_unlock_type_1 then

end if achievement_unlock_type_2 then

end if achievement_unlock_type_3 then

and so on and so forth. A switch case could do it like this and ignore all the unnecessary conditions:

switch (achievement) {
     case Achievement_type_1:
          // Do stuff
     case Achievement_type_2:
          // Do stuff
}

Switch cases are a great way to avoid end if spaghetti

2 Likes

Well this seems kind of vague, not a lot to go off of, but here

local achievement_unlock_types = {achievement_unlock_type_1, achievement_unlock_type_2, achievement_unlock_type_3}

for _, unlock_type in pairs(achievement_unlock_types) do
    if unlock_type then
        
    end
end

If there’s a reason you can’t do this lmk

2 Likes

I would be glad to have this! This would probably allow more optimizations to the code and not breaking the first statement while looking for more applications sounds too good to be true. The thing is that it’s limited to only one conditions.

For the colon syntax, I wouldn’t suggest to have it on Lua.

2 Likes

The way it works on the side of requirements doesn’t work like that. I tried using for loops first and it did not work

2 Likes

You can store functions in table variables. This is the approach I would take if you prefer to avoid using if statements.

local achievement_unlock_types = {
	['achievement_unlock_type_1'] = function()
		--Function script here
	end,
	['achievement_unlock_type_2'] = function()
		--Function script here
	end,
	['achievement_unlock_type_3'] = function()
		--Function script here
	end,
}

local achievment_function = achievement_unlock_types[achievment here]
achievment_function()
7 Likes

Pluto does this very well, If switch cases do come I also want passthrough and a syntax maybe like this:

switch MYVAL do
 case 20 do
 case 10 do
  print(`{MYVAL} is 10 or 20`)
  break
 end
 default 
  print(`{MYVAL} is not 10 or 20`)
 end
end
3 Likes

When handling alot of possible states and when some states have the same result, rather than doing color == "blue" or color == "green" a simple:

case "blue" do
case "green" do
-- code

can be applied.


Also I know this is unrelated to the whole switch-statement conversation but I think gotos will also be really cool and provide a HUGE performance increase for many programs that require moving from part to part of the program without using functions. Especially if it is implemented in an optimized fashion.

3 Likes

For context, Apakovtac and zeux are both engineers on the Luau team, so this is going to be a pretty definitive no, at least in the specific form of switch statements.

What is more likely is an equivalent to match expressions. Here is some prior art:

They’re like more powerful switch statements, in that you could do something like this (using a pretend Rust/Luau syntax as an example)

let x = match part.position {
    Vector2(1, 1) => "top right",
    Vector2(x, 1) => `{x}, right`,
    Vector2(1, y) => `top, {y}`,
    Vector2(x, y) => `{x}, {y}`,
}

But this is not a promise and will not happen soon.

Anything with some sort of fallthrough is also very unlikely to me–fallthrough is something modern languages don’t really implement to my knowledge, and even modern C++ codebases will actively lint against them, requiring some sort of explicit marker.

7 Likes

In the 13 years I’ve been writing Lua code on Roblox I have never once run into a scenario where I wanted to use a switch statement. Lua’s simplicity & limited syntax is what makes it approachable.

The only reason for a switch statement that I can think of is to shorten some if-else code by a few lines, but in cases where you have a long string of if-statements you want to replace with a switch-statement, there are probably way better solutions. For example when programming keyboard movement, instead of using this:

function processKey(key)
  if key == Enum.KeyCode.W then

  elseif key == Enum.KeyCode.A then

  elseif key == Enum.KeyCode.S then

  elseif key == Enum.KeyCode.D then

  end
end

You could use a dictionary instead, such as:

local inputFunctions = {
  [Enum.KeyCode.W] = func1;
  [Enum.KeyCode.A] = func2;
  [Enum.KeyCode.S] = func3;
  [Enum.KeyCode.D] = func4;
}

function processKey(key)
  inputFunctions[key]()
end
12 Likes

just make ur own

local function switch(case, callbacks)
    return callbacks[case]()
end

switch(
    'case1',
    {
        ['case1'] = function()
            print('sup')
        end;
        ['case2'] = function()
            print('soup')
        end;
    }
)
3 Likes