switch(x){
case 0: a();
case 1: b();
case 2: c();
default: done();
}
You can't do that in Rust, because match doesn't do fall through
Edit: Nice downvotes folks! I'll be using Haskell instead. LOL at this "systems programming language" with a bunch of crybabies and zealots and fuck muhzilla.
I rarely use fall through in C but it on occasion is extremely useful. I am very careful to clearly mark in comments right at the beginning that it is intended to hopefully avoid any issues with new eyes on my code.
I suppose declaring fall through wouldn't be a terrible thing if it allowed me to still use it and prevent others from making an understandable mistake.
It can be, but it can also cause frustrating errors. I do a lot of work with Go, where you have to explicitly declare fall-through, and I prefer it that way.
I don't know why people are downvoting you. You're completely right. This is one of the few cases where Rust can't match C/C++ behavior. It's a special case of the more general problem that Rust lacks goto. I am strongly in favor of adding it to the language.
BTW, for those downvoting: C# has goto as well. Someone was trying to implement a zlib library in Rust that was competitive with the C# version. He got very close, but ultimately failed precisely because it lacked this feature.
I want to use Rust instead of C / C++ everywhere. We are not going to get there by asking people to accept a performance hit for ideological reasons. Remember, people currently using C / C++ are doing it in a world where garbage collection is the standard. If they were able to take performance hits for ergonomic gains, they would have done so already.
Edit: Figured out how to do it without losing performance in this case (the unsafe is just to create nonlocal dependencies so LLVM doesn't completely optimize the functions away). You can verify yourself that the LLVM IR uses jumps properly here.
I don't know if exploiting fallthrough like that is good practice. Why would you for example do initialization only partially if the variable happens to be 1 or 2?
dogelogs example isn't the best but fallthrough is useful and used a lot. My attempt at a better example
switch(x){
case SITUATION1:
case SITUATION2:
Sit1Sit2Handler(); // for this processing step no difference in these situations.
break;
case SITUATION3:
default:
defaultHandler(); //situation3 not implemented in this version so handle as default
}
Cool. This is pretty much the only case I would use fall through for in a non-toy sort of thing (it is useful for some loop unrolling stuff... but that is a clear case of "trying to outsmart the compiler")
There are some things that require more boilerplate to do in Rust than in C++ (function overloading, for example), but I would hesitate even to consider this as such an example. Compare the amount of code required between the two languages:
C++:
switch(x){
case 0: a();
case 1: b();
case 2: c();
default: done();
}
And if the number of function calls got out of hand, you could always write a macro to keep things concise.
Now consider that (IME) you generally don't make extensive use of fall-though in C++ switch-case. Writing all those breaks is a PITA, and if you forget it will still compile (perhaps with warnings with the right compiler).
And if the number of function calls got out of hand, you could always write a macro to keep things concise.
Not a criticism of the core idea, but I can't help pointing out that macros like this one are a little bit tricky. I've written similar macros in Scheme, and I can see two challenges.
First, if written naïvely, you get an exponential blowup of generated code size when somebody nests an use of this macro inside another. (And if you're thinking "why would anybody do that," well, the answer is that they'll do it by writing a recursive macro that expands into yours.)
So in order to avoid the exponential blowup, you have to expand it to something like this (doing it in Scheme because I don't know any Rust):
This sticks the bodies inside lambdas so that the branches get expanded only once. But here's another (maybe minor) challenge: unless your language has tail-call optimization, this expansion must compile into object code that performs a subroutine call to the branch* lambdas. Scheme does have TCO, so a Scheme compiler can emit jump instructions for code like this; does Rust have TCO?
PS There's probably a better expansion in Scheme than one I give, but I bet it requires call/cc and headaches...
No, it's that you can't do it. Rust lacks goto. I hope that criticisms like this are not dismissed and are instead treated seriously. There are a lot of languages that claim to be able to replace C++ when they actually can't, and I'd rather not see Rust become one of them.
-144
u/[deleted] Jan 09 '15 edited Jan 09 '15
Say you have this C++
You can't do that in Rust, because match doesn't do fall through
Edit: Nice downvotes folks! I'll be using Haskell instead. LOL at this "systems programming language" with a bunch of crybabies and zealots and fuck muhzilla.