Open Daniel-Cortez opened 4 years ago
Neat syntactic sugar. A side note I'd like to leave, the second example you provided is more optimized than the first one.
Well, I wouldn't call it only a syntactic sugar, as it also has potential for more optimal compiled code (less duplicated code for storing the value into a variable etc.)
Also, I experimented with this concept back in December (just didn't get around to post about it until now) and have a working implementation since then. @pawn-lang, would it be OK if I make a draft PR to showcase it?
So I do have a few thoughts:
1) If there were some integration of more expression-control, it should maybe be more general than just switch
, but I don't yet know how much further. We already have expression-if essentially (?:
). What about expression functions?
2) Speaking of which, you compared this to two existing versions, but not the most direct comparison:
new level = PlayerInfo[playerid][pMechSkill];
new Float:fueltogive =
(0 <= level < 50) ? 2.0 :
(level < 100) ? 4.0 :
(level < 200) ? 6.0 :
(level < 400) ? 8.0 :
10.0 ;
Or more accurately matching your switch expression example:
new level = PlayerInfo[playerid][pMechSkill];
new Float:fueltogive =
(0 <= level <= 49) ? 2.0 :
(50 <= level <= 99) ? 4.0 :
(100 <= level <= 199) ? 6.0 :
(200 <= level <= 399) ? 8.0 :
10.0 ;
A tiny bit more verbose, but already exists.
3) I'm in two minds about the overloading of _
. For one, it already has at least two uses, one of which is as a tag, so using the _:
syntax, and is a valid symbol name as well. On the other hand, the other use is for default parameters, so has some precedent as meaning default
.
An alternate syntax could be to do away with _:
altogether. It's a bit strange having the trailing ;
in your first example, and the second example does away with it anyway, so why not embrace that?
new Float:fueltogive = switch (PlayerInfo[playerid][pMechSkill];
0..49: 2.0;
50..99: 4.0;
100..199: 6.0;
200..399: 8.0;
10.0
);
Making the syntax something like:
switch (<var>;[<case>:<result>;]*<default>)
Thus even switch (var; 5)
becomes valid. This would be the only instance where ;
was valid in an expression though, which goes back to my first point about making it more generic somehow.
Having said that:
4) why get rid of case
and default
at all? That's just introducing two ways of doing the same thing in different places.
5) Have you tested this with tag overrides?
We already have expression-if essentially (
?:
). What about expression functions?
From how I can imagine it, expression functions would require reimplementation of almost all functionality and workarounds of regular functions, such as:
new
and static
.
1.2. Destructors.
1.3. Ability to access local variables from the containing function.In other words, the idea of expression functions is clearly much more far-fetched compared to switch expressions.
It's a bit strange having the trailing
;
in your first example, and the second example does away with it anyway
Yes, I intended the trailing ;
after the default case to be optional, as otherwise it might look strange when the whole switch expression is being put on one line. This is not something new, as we already have optional trailing semicolons in enumerations.
This would be the only instance where
;
was valid in an expression though
And this is exactly why I used it (or rather had to). Originally I wanted to use ,
instead, but since it already can be used in expressions, the part after ,
would be misinterpreted as a part of the expression (for example, 1: 5, 2,3: 4
would be read as 1: (5, 2,3): 4
, which would result in a syntax error). Therefore I needed something that can't be interpreted as a part of expression, and since ;
is already used to end expressions/statements, it seemed as the most reasonable option.
why get rid of
case
anddefault
at all?
Mainly because of less verbose syntax, which could be more convenient for putting the whole expression on a single line. (Also I could or couldn't have been inspired by the syntax of switch expressions in C#.)
Have you tested this with tag overrides?
Yes, I tested tag overrides on both case values and expressions that follow them.
To begin with, we already have switch statements, where tag overrides can't be used on case values directly (for example, case Tag:0:
is incorrect syntax), but the said value can be wrapped in parentheses along with the tag override (so case (Tag:0):
would be valid). I think the same rule should apply to switch expressions as well, especially since _:
is reserved for default cases.
Regarding the expressions that follow each case, they're parsed in a standard manner, with function expression()
from sc3.c, which also handles tag overrides. Also all tags in both case values and expressions are checked for tag mismatch.
By expression functions I just meant:
stock GetSomeVar() gSomeVar;
Not local functions.
By expression functions I just meant:
stock GetSomeVar() gSomeVar;
Not local functions.
Then how would this be supposed to work?
stock Func() random(10);
Would Func()
be an "expression function" returning a random number, or rather a normal function that returns nothing?
Though, even if we try to implement something similar, maybe we should discuss this concept in a separate issue?
Also, regarding switch expressions, as I mentioned earlier, I already have a working implementation. Would anyone mind if I make a PR that demonstrates its functionality?
Issue description:
This feature is not really that new in general; you could have already seen it in C#, Java, Rust and other languages.
In some situations an ability to use
switch
in expressions could be very handy. For example, let's suppose we have the following code: https://github.com/NextGenerationGamingLLC/SA-MP-Development/blob/a059abaebda0f2dff3c2e0f95ee4c9c5696406c7/GMs/includes/core/acceptcancel.pwn#L2604..L2612or https://github.com/NextGenerationGamingLLC/SA-MP-Development/blob/a059abaebda0f2dff3c2e0f95ee4c9c5696406c7/GMs/includes/core/acceptcancel.pwn#L2209..L2215
(NOTE: originally the second example actually had
PlayerInfo[RefillOffer[playerid]][pMechSkill]
instead ofPlayerInfo[playerid][pMechSkill]
, but I changed it here for the sake of simplicity.)With switch expressions the examples above could be simplified to something like this:
or this:
Please note that this is only a draft syntax which may be changed later; I'm open to suggestions.
Minimal complete verifiable example (MCVE):
Workspace Information: