GOTO for Luau (I think)

IDK if this is useful at all but I thought it was cool so here guys

local goto = debug.info(1, "f")

if ... == "foo" then -- ::foo::
	print("Wassup")
	return -- Important or it will go in a loop
end

print("Ok")
goto "foo"

Prints

Ok
Wassup
10 Likes

Cool concept!
I wonder if this messes up the stack trace in anyway lol

Well, as far as I can see, it’s more of a recursive caller than an actual goto. So if you do this in a nested call way, you’re definitely going to have stack overflow at some point. Basically this method is equivalent to:

local function call()
   call() -- calls itself recursively
end
2 Likes

Yeah I was kind of tired when I made this now When I double check I realize it is kind of trash version of Goto

It’s neat, but I want to point out that goto is a code smell

1 Like

I believe how this works is that debug.info(1, "f") returns the entire program as a function, and how the labels are defined using if ... == "foo" then the ... represent the input arguments. So when running goto "labelName", it is like calling the entire program itself and setting ... to "labelName".

2 Likes

This is not a goto, it is a recursive call. debug.getinfo(1, "f") returns the main closure for the script, which is always variadic, hence a guard statement like if ... == can be used to return before blowing up the stack depth.

print(debug.getinfo(1, "a")) -- 0, true

There is some nuance in the implementation details, but nothing is inherently wrong with goto statements. They work well for exiting nested loops (however, labeled loops are a neater solution), implementing finite state machines, and optimizing tail call recursions in some contexts.

1 Like

Sure, goto can be useful in some very specific scenarios, but for most code you should not be thinking “yeah, goto is a good solution to this.” Sure, maybe something like

-- guard clauses that share the same 
if ... then goto cleanup end
if ... then goto cleanup end
if ... then goto cleanup end
...
::cleanup::
    -- cleanup logic

but even still, I’d just define a function for cleanup and call that.

1 Like