Things Rust shipped without
101–110 of 330 posts
Re: Things Rust shipped without
#102What about things that Rust shipped without that should have been included?
Coroutines, Go style.
Re: Things Rust shipped without
#103Earlier quoted context omitted.
Why "might as well"? Things can be optimal in some places and suboptimal elsewhere.
Consistency is valuable. If some blocks have different rules to other blocks that's a real downside.
Re: Things Rust shipped without
#104How does one accomplish loop-unrolling as in Duff's Device in rust, if case statements do not fall through?
Well, you generally don't, because Duff's Device isn't generally regarded as a good idea anymore, in my understanding: > It turns out that with branch predictions and the relative speed of CPU > vs. memory changing over the past decade, loop unrolling is pretty much > pointless. http://lkml.iu.edu/hypermail/linux/kernel/0008.2/0171.html
int remaining = length % 4;
switch (remaining) {
case 3: h ^= (data[(length & ~3) + 2] & 0xff) Re: Things Rust shipped without
#105Earlier quoted context omitted.
I don't think I've written a goto since the 1970s, and I've written a lot of code since then. If you need to bail out of something in the middle, make it a function.
As mentioned above, in C goto is often useful for error handling (where you need to free some resources before exiting the function). It's way more convenient and readable to write freeing code once and jump to it instead of having multiple return exits and duplicate the code before every single one of them.
static int foo_impl(int arg, int **resource1, int **resource2) {
*resource1 = (int *)malloc(sizeof(**resource1));
if (*resource1 == NULL) return EXIT_FAILURE;
/* Do something with resource1 (omitted)... */
*resource2 = (int *)malloc(sizeof(**resource2));
if (*resource2 == NULL) return EXIT_FAILURE;
/* Do something with resource1 and resource2 (e.g.,
stick them in a global hash table as key/value pairs,
or whatever, omitted)... */
return EXIT_SUCCESS;
}
int foo(int arg) {
int *resource1;
int *resource2;
int ret;
resource1 = resource2 = NULL;
ret = foo_impl(arg, &resource1, &resource2);
if (ret != EXIT_SUCCESS) {
free(resource2);
free(resource1);
}
return ret;
}
The advantages are that it makes it very explicit which resources need to be cleaned up (making it easier to review to be sure you haven't forgotten one, or forgotten to initialize one, because they're in a nice list), and it's harder to screw up the control flow. You can't get out of the function without passing by the clean-up code, and you can't accidentally fall into the clean-up code without explicitly returning an error.Re: Things Rust shipped without
#106What about things that Rust shipped without that should have been included?
Re: Things Rust shipped without
#107Earlier quoted context omitted.
rustfmt (currently in development) follows this principle.
Please don't make it an option. Use one format to rule them all, as with "gofmt". I don't care what it is, but pick something and standardize.
Every language carries with it a culture. The culture of Go is one which allows for gofmt to define one true style and refuse to deviate, just as it allows the language designers to refrain from adding generics.
The culture of Rust is not like that, for several reasons. For one, the Rust community loves a good bikeshed. For two, the syntax of Rust is more complicated than Go, and includes situations (match statements & where clauses come to mind) in which people are just going to want to different things.
I know the advantages of one true style - everyone's heard the arguments - and there's a sane, median default as the official style guide, which will be rustfmt's default output. That seems like a good compromise.
Re: Things Rust shipped without
#108Earlier quoted context omitted.
union foo { int x; float y; }; union foo bad; bad.x = 100; printf("%f\n", bad.y); // undefined behavior (though usually works)
Which is actually a useful feature in some obscure optimizations, like this fast (approximate) square root: float half_r=r*0.5F; union { float y; int32_t i; }; y=r; i=0x5f375a86-(i>>1); y=y*(1.5F-(half_r*y*y)); return y;
Re: Things Rust shipped without
#109Earlier quoted context omitted.
Well, you generally don't, because Duff's Device isn't generally regarded as a good idea anymore, in my understanding: > It turns out that with branch predictions and the relative speed of CPU > vs. memory changing over the past decade, loop unrolling is pretty much > pointless. http://lkml.iu.edu/hypermail/linux/kernel/0008.2/0171.html
Still, there are cases where fall-through can be useful: int remaining = length % 4; switch (remaining) { case 3: h ^= (data[(length & ~3) + 2] & 0xff)
Re: Things Rust shipped without
#110Earlier quoted context omitted.
> Why should I even care about stuff like this being "considered poor style" by the creators of Rust? Maybe you are writing code for the Rust standard library, where following the core projects style recommendations would be important for consistency. Maybe you don't want to start from scratch coming up with your own style, and want a decent starting point from which you can vary as your team figures out what does/do…
Style recommendations are great and if I was writing code for the standard library, I would certainly follow them. But they don't simply recommend their style. "We recommend doing this like that" is very different from "Doing this that way is considered poor style". That sounds like their recommendations were objective facts and you shouldn't do anything else, even if that worked better for you and the majority of ot…
On the one hand, it is an objective fact that it is considered, by the authors, poor style.
On the other hand, that it is "considered" anything is an explicit (not merely implicit) statement that it is subjective (and "poor style" -- or good style, for that matter is inherently subjective in any case.) So, characterizing that language as making it sound "like their recommendations are objective facts" seems quite bizarre.