4 ms·
Reading over the examples, it seems like there's a lot of good stuff here, though I wondered how possible it would be to extend switch with some of this capabil
by mikepurvis 7y ago
Reading over the examples, it seems like there's a lot of good stuff here, though I wondered how possible it would be to extend switch with some of this capability vs adding a new keyword. It looks like this possibility was considered and is addressed in §7.2— basically the flexibility of case labels and break statements being able to appear inside control structures leads to all kinds of chaotic corner cases for switch (Duff's Device and friends) that are incompatible with the proposed semantics for inspect, with no obvious way to signal from the source which one you want.
- jupp0r 7y agoSeems like `inspect` would turn `switch` into a deprecated practice, which is preferable imho. This way, it's easier to write clang-tidy rules for conversion and to raise red flags in PRs.
- mikepurvis 7y agoYeah, it makes sense. It's just a bummer when switch feels like a much better-named keyword for the functionality, in the long term. You almost wonder if they could do something like how `enum` got fixed up with proper scoping as `enum class`. Like, could `switch` retain the legacy functionality with the new stuff triggered when you do `switch from`, `switch if`, or similar. Or there could be new keyword added after the parenthesis, something like: switch(<thing>) cases { <opt1> : ...; <opt2> : ...; __ : ...; } This has a clear connection back to the legacy command in terms of a switch always having either case labels or a cases structure. And zero chance of breaking existing code, given that the `cases` keyword would only be valid in that position and could still be used as an identifier elsewhere (though obviously that would be discouraged).
- twic 7y agoOr even just have a rule that if a switch uses patterns, it can't have any of the weird legacy misfeatures.
- mikepurvis 7y agoI think it's just hard because they really are completely different in behaviour. A conventional switch is just selecting an integer value— under the hood it can be a jump table, a binary search, or something else entirely. This, on the other hand, is always going to be an if-cascade.
- twic 7y agoThat's an implementation question, which seems orthogonal to questions of syntax and semantics. As for efficiency, we have decades of experience of compiling pattern matching, so i would be surprised if it was always just an if-else ladder. The authors of the proposal to add it to Java think that, compared to explicit if-elses, "it is more optimizable too; in this case we are more likely to be able to do the dispatch in O(1) time": https://openjdk.java.net/jeps/8213076 https://openjdk.java.net/jeps/8213076 I imagine this is through approaches which convert the cases to integers, and then do a traditional jump table etc.
- int_19h 7y ago"inspect" is weirdly apropos, because it hearkens back to Simula-67 (which used it for what we'd call type switch today - so, a subset of pattern matching). The original C++ syntax borrowed a lot from Simula.
- edflsafoiewq 7y agoswitch is an extremely useful control structure, though needed rarely. It's basically a kind of computed goto, something not found very often outside C/C++ anymore. If there's a real inspect, people will be able to stop treating switch as a deficient approximation to one, and maybe appreciate it for what it is.
- dvt 7y agoSwitch is used pretty often when UI needs to look different based on certain application states (consider any 3+ state button). I was curious if I used it recently, and, in fact, here it is in some code I wrote a few months ago[1]. It's also used all the time (also happens to be fairly idiomatic) when dealing with Redux, MobX, etc. [1] https://github.com/dvx/lofi/blob/master/src/renderer/components/Lofi/Cover/index.tsx#L232 https://github.com/dvx/lofi/blob/master/src/renderer/compone...
- edflsafoiewq 7y agoBut that, like most uses of switch, is essentially uninteresting as a control-flow construct. It's just a stylistic point to use a switch here instead of an if or a match. JS's switch has no extra power other than fallthrough anyway. Here's a poor-man's coroutine (with serializable state!) where switch plays a more interesting role. void move_robot(state* s) { switch (s->resume_at) { case 0: #define SUSPEND(resume_pt) s->resume_at = resume_pt; return; case resume_pt:; #define PAUSE(resume_pt) s->pause_time = 20; while (s->pause_time) { SUSPEND(resume_pt) } for (;;) { /* three knight moves, then forward */ for (s->i = 0; s->i != 3; s->i++) { forward(s); PAUSE(1); forward(s); PAUSE(2); turn_left(s); forward(s); PAUSE(3); } forward(s); } } }
- saagarjha 7y agoSwitches are quite useful when you have a finite set of options you want to match against.
- stabbles 7y agoYeah, it creates a jump table, so basically an O(1) operation in assembly rather than O(n) comparison worst case for every case. However, this means switch _only_ works with integers, which is rather limited and confuses newcomers. For instance this does not compile: void f(std::string const &str) { switch(str) { case "option_1": std::cout << "First option\n"; break; case "option_2": std::cout << "Second option\n"; break; default: std::cout << "None of the above\n"; } }
- ramenmeal 7y agoc# has been adding pattern matching capabilities to the switch statement and I think it's created a mess. Both syntax wise and possible bug prone. Switch went from choosing a distinct case to matching multiple cases. I'm sure Mads knows more than me though, so it's probably a safe change.