Strict switch

php.internals

David Rodrigues

5 years ago
Hello! With PHP 8 we have match(), that is a switch strict expression-like. But strict is not strict, and it could cause confusion because switch() and match() are pretty similar. I believe that this has already been discussed, but it would be interesting to re-evaluate the possibility of a strict() with support for strict. In order not to generate BC, my suggestion is to attach a specific keyword for this purpose, or a similar alternative. (0) switch(8.0) { case '8.0'; return 'no'; case 8.0: return 'yes'; } // no? (1) strict switch(8.0) { case '8.0'; return 'no'; case 8.0: return 'yes'; } // yes (2) switch strict(8.0) { ... } // yes (3a) switch(8.0, true) { ... } // yes (3b) switch(8.0, strict: true) { ... } // yes (named argument) Or then in the "case": (4) switch(8.0) { strict case 8.0: ... } // yes (5) switch(8.0) { case strict 8.0: ... } // yes Or allowing operators (this would be the most flexible way, as it would allow for a number of other features): (6) switch(8.0) { case === 8.0: ... } // yes Atenciosamente, David Rodrigues

Sara Golemon

5 years ago
On Thu, Nov 26, 2020 at 10:39 AM David Rodrigues <david.proweb@gmail.com> wrote:
> With PHP 8 we have match(), that is a switch strict expression-like. But > strict is not strict, and it could cause confusion because switch() and > match() are pretty similar. > >
I agree that PHP deserves the ability to do strict comparisons when requested and that match won't serve all of switch's use cases. This idea has come up a few times in the past, but I think we can perhaps get further with it now that the language is growing more strict-friendly.
> (1) strict switch(8.0) { case '8.0'; return 'no'; case 8.0: return 'yes'; } > // yes >
Introducing new keywords automatically has a higher bar to acceptance than not, so while this certainly reads well, we do have to consider the impact to existing code defining clases/functions named 'strict'.
> (2) switch strict(8.0) { ... } // yes > (3a) switch(8.0, true) { ... } // yes >
I'm not a fan of how either of these read. The first on wholly aesthetic grounds, the latter on opacity. The meaning of "true" is inobvious here.
> (3b) switch(8.0, strict: true) { ... } // yes (named argument) > >
This I like now that we have named arguments. It's a psuedo named argument, but I don't think that distinction matters too much from the userland perspective. Implementation might be a little on the ugly side though, so let's keep it in the maybe pile.
> Or then in the "case": > > (4) switch(8.0) { strict case 8.0: ... } // yes > (5) switch(8.0) { case strict 8.0: ... } // yes > > Or allowing operators (this would be the most flexible way, as it would > allow for a number of other features): > > (6) switch(8.0) { case === 8.0: ... } // yes > >
These formats have been proposed previously, and I think they're the worst of the lot because now you have a comparison that is potentially sometimes strict and sometimes not. This has the highest potential for surprise. The main question I'd put to you is this: Are there other parts of the language where a strictness modifier would also make sense, or is it unique to `switch`. I suspect it's not, so list out those syntaxes and identify how the proposed options would translate to them. A general purpose winner may float itself to the top. -Sara

Nikita Popov

5 years ago
On Thu, Nov 26, 2020 at 5:39 PM David Rodrigues <david.proweb@gmail.com> wrote:
> Hello! > > With PHP 8 we have match(), that is a switch strict expression-like. But > strict is not strict, and it could cause confusion because switch() and > match() are pretty similar. > > I believe that this has already been discussed, but it would be interesting > to re-evaluate the possibility of a strict() with support for strict. > > In order not to generate BC, my suggestion is to attach a specific keyword > for this purpose, or a similar alternative. > > (0) switch(8.0) { case '8.0'; return 'no'; case 8.0: return 'yes'; } // no? > > (1) strict switch(8.0) { case '8.0'; return 'no'; case 8.0: return 'yes'; } > // yes > (2) switch strict(8.0) { ... } // yes > (3a) switch(8.0, true) { ... } // yes > (3b) switch(8.0, strict: true) { ... } // yes (named argument) > > Or then in the "case": > > (4) switch(8.0) { strict case 8.0: ... } // yes > (5) switch(8.0) { case strict 8.0: ... } // yes > > Or allowing operators (this would be the most flexible way, as it would > allow for a number of other features): > > (6) switch(8.0) { case === 8.0: ... } // yes > > > > Atenciosamente, > David Rodrigues >
I think the better direction here would be to improve match() such that it can replace more of the current switch use cases. If match supported block expressions, then most uses of switch() could use match() instead, and as such make use of the strict comparison semantics. Only switches that make use of non-trivial fallthrough behavior could not be easily expressed using match. Nikita

Larry Garfield

5 years ago
On Mon, Nov 30, 2020, at 9:09 AM, Nikita Popov wrote:
> On Thu, Nov 26, 2020 at 5:39 PM David Rodrigues <david.proweb@gmail.com> > wrote: > > > Hello! > > > > With PHP 8 we have match(), that is a switch strict expression-like. But > > strict is not strict, and it could cause confusion because switch() and > > match() are pretty similar. > > > > I believe that this has already been discussed, but it would be interesting > > to re-evaluate the possibility of a strict() with support for strict. > > > > In order not to generate BC, my suggestion is to attach a specific keyword > > for this purpose, or a similar alternative. > > > > (0) switch(8.0) { case '8.0'; return 'no'; case 8.0: return 'yes'; } // no? > > > > (1) strict switch(8.0) { case '8.0'; return 'no'; case 8.0: return 'yes'; } > > // yes > > (2) switch strict(8.0) { ... } // yes > > (3a) switch(8.0, true) { ... } // yes > > (3b) switch(8.0, strict: true) { ... } // yes (named argument) > > > > Or then in the "case": > > > > (4) switch(8.0) { strict case 8.0: ... } // yes > > (5) switch(8.0) { case strict 8.0: ... } // yes > > > > Or allowing operators (this would be the most flexible way, as it would > > allow for a number of other features): > > > > (6) switch(8.0) { case === 8.0: ... } // yes > > > > > > > > Atenciosamente, > > David Rodrigues > > > > I think the better direction here would be to improve match() such that it > can replace more of the current switch use cases. If match supported block > expressions, then most uses of switch() could use match() instead, and as > such make use of the strict comparison semantics. Only switches that make > use of non-trivial fallthrough behavior could not be easily expressed using > match. > > Nikita
Disagree. switch is a procedural logic flow control. match is an evaluation expression. Things like fallthrough do not belong there, as it mushes expressions together in weird ways. match is lovely because its logic flow is simple and predictable. We should keep that. --Larry Garfield

Marco Pivetta

5 years ago
On Tue, Dec 1, 2020, 19:57 Larry Garfield <larry@garfieldtech.com> wrote:
> > > Disagree. switch is a procedural logic flow control. match is an > evaluation expression. Things like fallthrough do not belong there, as it > mushes expressions together in weird ways. match is lovely because its > logic flow is simple and predictable. We should keep that. >
Full ack: the power of the new expression is that it is in fact an expression. Adding procedural capabilities only makes it more complicated, and for that you can already shoot yourself in a foot with `switch`

Nikita Popov

5 years ago
On Tue, Dec 1, 2020 at 7:57 PM Larry Garfield <larry@garfieldtech.com> wrote:
> On Mon, Nov 30, 2020, at 9:09 AM, Nikita Popov wrote: > > On Thu, Nov 26, 2020 at 5:39 PM David Rodrigues <david.proweb@gmail.com> > > wrote: > > > > > Hello! > > > > > > With PHP 8 we have match(), that is a switch strict expression-like. > But > > > strict is not strict, and it could cause confusion because switch() and > > > match() are pretty similar. > > > > > > I believe that this has already been discussed, but it would be > interesting > > > to re-evaluate the possibility of a strict() with support for strict. > > > > > > In order not to generate BC, my suggestion is to attach a specific > keyword > > > for this purpose, or a similar alternative. > > > > > > (0) switch(8.0) { case '8.0'; return 'no'; case 8.0: return 'yes'; } > // no? > > > > > > (1) strict switch(8.0) { case '8.0'; return 'no'; case 8.0: return > 'yes'; } > > > // yes > > > (2) switch strict(8.0) { ... } // yes > > > (3a) switch(8.0, true) { ... } // yes > > > (3b) switch(8.0, strict: true) { ... } // yes (named argument) > > > > > > Or then in the "case": > > > > > > (4) switch(8.0) { strict case 8.0: ... } // yes > > > (5) switch(8.0) { case strict 8.0: ... } // yes > > > > > > Or allowing operators (this would be the most flexible way, as it would > > > allow for a number of other features): > > > > > > (6) switch(8.0) { case === 8.0: ... } // yes > > > > > > > > > > > > Atenciosamente, > > > David Rodrigues > > > > > > > I think the better direction here would be to improve match() such that > it > > can replace more of the current switch use cases. If match supported > block > > expressions, then most uses of switch() could use match() instead, and as > > such make use of the strict comparison semantics. Only switches that make > > use of non-trivial fallthrough behavior could not be easily expressed > using > > match. > > > > Nikita > > Disagree. switch is a procedural logic flow control. match is an > evaluation expression. Things like fallthrough do not belong there, as it > mushes expressions together in weird ways. match is lovely because its > logic flow is simple and predictable. We should keep that. >
Sorry if the phrasing was unclear. I'm not suggesting to add fallthrough support. Fallthrough was mentioned as the one thing that match cannot and should not support by design. I'm referring to support for non-trivial expressions, aka blocks. Say, the ability to split up a long expression by using a meaningful temporary variable. Block support is sufficient to cover *most* switch use-cases, obviating the need to introduce a new switch variant. Regards, Nikita

Stas Malyshev

5 years ago
Hi!
> I'm referring to support for non-trivial expressions, aka blocks. Say, the > ability to split up a long expression by using a meaningful temporary > variable. Block support is sufficient to cover *most* switch use-cases, > obviating the need to introduce a new switch variant.
We could take a page from Scala book and designate a return value to a block (of course, no reason to bother if it's not used) - which should make it relatively easy to add blocks in any expression context.
-- Stas Malyshev smalyshev@gmail.com