• Hello [name]! Thanks for joining the GMC. Before making any posts in the Tech Support forum, can we suggest you read the forum rules? These are simple guidelines that we ask you to follow so that you can get the best help possible for your issue.

Discussion Unuseful GML keywords

there are some GML keywords that reduce the lexical options, I do think that the number of reserved words should be left to an essential minimum.
The keywords I'm referring to are:

begin

end

exit

a lot of times even more now that we can define functions I find myself wanting to make a "end" or "exit" function.
Is there a good reason for these keywords (reserved words) to still be used?
do they provide some essential features?

other reserved words are and, or, not (I do know that some of these are for making it easier for newcomers to understand the logical expressions).
 

O.Stogden

Member
Exit is a fairly standard function in languages such as C++, so it would make sense to keep it, as it's useful for backing out of an entire code block if continuation is no longer needed. I use it quite a few times in my game.

I've never used any of the other keywords, but I'm guessing some do.

It appears that begin/end/and/or/not are purely words that do the job that symbols do, but I've always just used the symbols for it instead.

Exit is the only one I see that is strictly "required" as it were.
 

BiTrunade

Member
there are some GML keywords that reduce the lexical options, I do think that the number of reserved words should be left to an essential minimum.
The keywords I'm referring to are:

begin

end

exit

a lot of times even more now that we can define functions I find myself wanting to make a "end" or "exit" function.
Is there a good reason for these keywords (reserved words) to still be used?
do they provide some essential features?

other reserved words are and, or, not (I do know that some of these are for making it easier for newcomers to understand the logical expressions).
You can add an underscore before those reserved words and it will fixed. _exit, _end, etc.

You can also get into the habit of typing f_* before function/script names, therefore no confliction with GameMaker reserved keywords.

The keyword exit caught my interest, how would you want them to be named otherwise? I would never imagine a programming language without exit to end the code.
 

kburkhart84

Firehammer Games
The original GM was using Delphi(as I understand it). Instead of brackets, delphi has begin/end. Mark Overmars wanted to keep things easy and those were never taken out.

Exit...if I remember correctly is used for getting out of an event right then. If you are inside of a function, you can easily just "return" but since events aren't actually functions(as far as our side is concerned when we write GML), you use the exit keyword instead.

So yeah, those aren't "Unuseful" by any means. I agree that begin/end aren't really needed as we can just use brackets. And the others you mention(and, or, not) are done quickly with (&&, ||, !), and so could also be removed. I don't know if they are ever going to though since they like GML to be easy for newer people and "and" is easier to understand right away over "&&" for many people who have never coded before.
 

Alice

Toolmaker of Bucuresti
Forum Staff
Moderator
As of 2.3+, possibly even earlier, you can use blank return; instead of exit;, I think.
I actually tend to use blank returns now, because that's how it works for most other languages; earlier I'd be forced to use exit;, because blank returns caused a syntax error, if I recall.
 
You can add an underscore before those reserved words and it will fixed. _exit, _end, etc.

You can also get into the habit of typing f_* before function/script names, therefore no confliction with GameMaker reserved keywords.

The keyword exit caught my interest, how would you want them to be named otherwise? I would never imagine a programming language without exit to end the code.
the exit keyword is actually the same as return

Regarding the f_* or even _* it doesn't look that intuitive to have a call as foo.f_exit() if you are calling it as a function it is a function foo.exit() makes more sense. the underscore behind the variables _* is actually a thing commonly used with local variables or private functions.
 

O.Stogden

Member
It might be due to them wanting to keep consistency with other languages (shocker I know).

In C++ both "return" and "exit" exist, but as Alice said, in C++, return will cause an error if it doesn't return a value (In C++).

If they want to bring GML in line with other languages, having both "exit" and "return" would do that, but who knows. I don't. :p
 

Bart

WiseBart
GameMaker has some other odd remains from the past in its language, such as assignments using := and <> to check for inequality (VB style) in comparisons, though I'm not sure if those things are still present in 2.3.

Didn't know about that use of return either. That's very interesting!
If there's no actual difference between return and exit then return could be used everywhere.

I do think it's interesting to leave and, or and not in since they could improve readability.
 

kburkhart84

Firehammer Games
Indeed, I had understood exit was only for events and return was for functions(previously scripts). It makes sense though as you are basically doing the same thing, except that events can't return anything.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
I still see people using begin and end in their code, and exit is often used too, since it can't always be replaced by return, as exit will not only exit a script it will also exit the current event that is being run, something you can't do with return as it will (or should, or used to... :p ) give a "return without context" error or something like that. So exit still definitely has it's uses.
 
exit is often used too, since it can't always be replaced by return, as exit will not only exit a script it will also exit the current event that is being run, something you can't do with return as it will
what do you mean by exit the current event that is being run?!
Does this apply to GMS2?!

I don't get any error at all... if the exit as been replaced in all its functionality.. then it could be removed as keyword along with begin and end.
 

TheouAegis

Member
I tried using exit inside a script called inside an event and it only exits the script. Calling exit inside a Execute Code action would indeed terminate the event, because code actions are not scripts, they're embedded code.

My GMS2 license is up, so I can't test any versions of GMS2, but the last time I used return, which I'm pretty sure I tested in GMS2, it wasn't interchangeable with exit.

I second getting rid of begin and end though. I try to use them all the time in my enumerators. If you can say we should be expected to not use begin or end out of the original context, then it can just as easily be said that people currently using them should be expected to use the symbols.


And does return without an argument really work the same as exit, granting the possibility for a moment that it can be used without an argument now? Does exit load values into the register like return? If not, then exit would technically be faster than return when no value is needed, and so exit would still have a place.
 
And does return without an argument really work the same as exit, granting the possibility for a moment that it can be used without an argument now? Does exit load values into the register like return? If not, then exit would technically be faster than return when no value is needed, and so exit would still have a place.
exit doesn't allow to return a value... so you must be right when you say that exit might be faster even though all scripts actually return undefined whether you use exit; or return; or nothing...
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
I have nothing against "exit", I'm using it often, I just wanted to point out that maybe empty reutrn; is equal to exit.
Did some checks on that, and you are correct. Return will now exit events without any errors, when it never used to. So, yeah, return and exit are absolutely interchangeable, with the exception of the fact that return from a function can return a value while exit can't. But other than that they function in the exact same way. Time to update the docs then. :)
 

Cpaz

Member
Maybe I'm just misunderstanding how this work, but what would be the use case of "exit"?
If you're just prematurely ending an event, then why write that code there to begin with? Just pull it out into a script/function (depending on your version) or just toss it outright.
 

Alice

Toolmaker of Bucuresti
Forum Staff
Moderator
Maybe I'm just misunderstanding how this work, but what would be the use case of "exit"?
If you're just prematurely ending an event, then why write that code there to begin with? Just pull it out into a script/function (depending on your version) or just toss it outright.
It can be useful if execution of further code depends on a specific condition. For example:
GML:
if (global.game_paused) {
    exit; // or return;
}

// do some input handling and game processing and stuff
(another matter altogether is whether we really want to implement pausing by "global.game_paused" variable - especially if the check for it must be included in multiple objects' events - but I digress)

The alternative is to put all further code in the opposite condition, but it adds some easily avoidable nesting to the code.
Don't know how about others, but given a choice between if (condition) { exit; } /* lots of further processing */ and if (!condition) { /* lots of further processing */ }, I'll generally pick the former.

--- EDIT ---

Possibly even more viable example, in some hypothetical dialogue controller object:
GML:
if (ds_list_empty(dialogue_list)) {
    instance_destroy();
    exit;
}

// otherwise, process the next dialogue command
 

Cpaz

Member
It can be useful if execution of further code depends on a specific condition. For example:
GML:
if (global.game_paused) {
    exit; // or return;
}

// do some input handling and game processing and stuff
(another matter altogether is whether we really want to implement pausing by "global.game_paused" variable - especially if the check for it must be included in multiple objects' events - but I digress)

The alternative is to put all further code in the opposite condition, but it adds some easily avoidable nesting to the code.
Don't know how about others, but given a choice between if (condition) { exit; } /* lots of further processing */ and if (!condition) { /* lots of further processing */ }, I'll generally pick the former.
I guess my question is why you wouldn't take all of the input in its own script and put that script call behind that condition. I guess it's ultimately up to preference at that point, but exit just makes things harder to read at a glance, IMO.

Possibly even more viable example, in some hypothetical dialogue controller object:
GML:
if (ds_list_empty(dialogue_list)) {
    instance_destroy();
    exit;
}

// otherwise, process the next dialogue command
I always got the impression, based on my experience with it's behavior, that instance destroy interrupted the event and called the destroyed event immediately. Maybe I'm misunderstanding that too. From what I read, the manual doesn't spell that out.
 

gnysek

Member
Maybe I'm just misunderstanding how this work, but what would be the use case of "exit"?
GameMaker before Studio, Game Maker Studio 1.x - as I wrote above, in those exit was quitting while event, while return was only quitting one "execute a piece of code" DnD action, and another in same event was still executed (if you used more than one). I was using this sometimes, as that was helping to skip one "if {}" condition at end of code which now requires "flag" variable.
This changed in GMS2, as DnD is converted to GML mode, and GML mode only allows one code editor per event.
 

kburkhart84

Firehammer Games
The alternative is to put all further code in the opposite condition, but it adds some easily avoidable nesting to the code.
Don't know how about others, but given a choice between if (condition) { exit; } /* lots of further processing */ and if (!condition) { /* lots of further processing */ }, I'll generally pick the former.
This is another form of the "early-out" method, except that with early-out you enforce running the quickest part first that you can(similar to ordering the && conditions of an if statement properly). I do it anywhere I can. The less code you run, the more efficient it is.... Having that extra set of brackets can be a pain, so doing the exit/return makes sense. I often a variable to false at the beginning, and then try to "prove" it is true, returning false each time it isn't, and finally returning true at the bottom otherwise.
 

Alice

Toolmaker of Bucuresti
Forum Staff
Moderator
I always got the impression, based on my experience with it's behavior, that instance destroy interrupted the event and called the destroyed event immediately. Maybe I'm misunderstanding that too. From what I read, the manual doesn't spell that out.
The manual does spell that out, but not in the main event it belongs to. Quoting the docs on Clean Up event:
For example, if you call instance_destroy() in the Step Event, then the Destroy Event will be called, then the Clean Up Event, and then the rest of the Step Event will finish running.
So yeah, adding an exit whenever you destroy an instance is pretty important if you don't want the subsequent code to run.

As for readability of the early exits - I suppose it depends on the dev's expectations and project conventions.
If dev is used to stopping the code at the end, early exit might surprise them.
On the other hand, if dev is famililar with early exits, they might appreciate the "flatter" look of the code and not needing to keep track of all these nested conditions you're in.
It's a matter of preference, really - and sometimes same dev might find different approaches preferable depending on specific cases. At any rate, with many people already using early returns and exits, there's no reason to stop supporting it (whether to remove exit; and always opt for return; is another matter altogether).
 

gnysek

Member
I remember that recently I've encountered problem, where I was calling instance_destroy() and because there was some code after it, game crashed, as it already unlinked instance, but still executed rest of step event. So, adding exit, or moving instnace_destroy() at end of event is crucial.
 
So yeah, adding an exit whenever you destroy an instance is pretty important if you don't want the subsequent code to run.
the subsequent code of the event still runs even if you call instance_destroy or even room_goto. The thing I was considering is.. do we really need exit now that return does exactly the same thing?!

I second getting rid of begin and end though. I try to use them all the time in my enumerators. If you can say we should be expected to not use begin or end out of the original context, then it can just as easily be said that people currently using them should be expected to use the symbols.
My original though was... "how much readable and cleaner does your code get when you use begin and end?" and the answer is "the code looks worst and is harder to read". That's why I suggested it :)
 

Alice

Toolmaker of Bucuresti
Forum Staff
Moderator
do we really need exit now that return does exactly the same thing?!
Not really, as long as blank return; is 100% functionally equivalent to exit; I wouldn't mind freeing the "exit" keyword. I was mostly addressing when you would use exit/blank return in the first place.

Same goes for begin/end - I wouldn't mind seeing these keywords here (and possibly other Delphi leftovers), personally.
Then again, these changes would need to be properly communicated ahead of time, so that people will know not to use these keywords anymore and what to use instead (also, clear uses of these keywords from docs, if there are some). Maybe there could even be a grace period where you can opt-in for the old keywords, but this might be too much effort for too little gain. I know they did add an option to enable/disable operators short-circuiting before having it enabled all the time; how much effort such a toggle would be (both in terms of UI and the underlying compilation), I don't know.
 

gnysek

Member
Lot of languages have some reserved words, which aren't in use (Javascript is probably the best example). I think that there are more important priorities than removing/merging keywords :) Also, some may be on list because of result languages, which also contains same keyword, and it's easier just to forbid it, rather than obfuscating on compile.
 
Top