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
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
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
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
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".
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.
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.