Earlier quoted context omitted.
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.
What the parent said still applies in your case. You just make a wrapper function that does the cleanup. I have used this pattern many times: 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)…
Things Rust shipped without
131–140 of 330 posts
Re: Things Rust shipped without
#132What about things that Rust shipped without that should have been included?
In C++, this would look like:
#include
class B { public: int get_id() { return id; }; int id; };
class C : public B { };
int main() { C c; std::cout
Maybe I'm ignorant, and there's an easy way to do this. I was screwing around with Rust a few months before 1.0 and didn't see any mention of it in the docs, though. (Everything I saw required me to provide an impl for functions defined in an interface for every class that implemented that interface.)Re: Things Rust shipped without
#133What about things that Rust shipped without that should have been included?
The ability to provide a default implementation of a function in a trait that can be inherited and used by "classes" that extend that trait. In C++, this would look like: #include class B { public: int get_id() { return id; }; int id; }; class C : public B { }; int main() { C c; std::cout Maybe I'm ignorant, and there's an easy way to do this. I was screwing around with Rust a few months before 1.0 and didn't see any…
Rust provides this. E.g., the "talk" method in the "Animal" trait below: [0]
trait Animal {
// Static method signature; `Self` refers to the implementor type
fn new(name: &'static str) -> Self;
// Instance methods, only signatures
fn name(&self) -> &'static str;
fn noise(&self) -> &'static str;
// A trait can provide default method definitions
fn talk(&self) {
// These definitions can access other methods declared in the same
// trait
println!("{} says {}", self.name(), self.noise());
}
}
[0] From Rust By Example, http://rustbyexample.com/trait.htmlRe: Things Rust shipped without
#134Earlier quoted context omitted.
What the parent said still applies in your case. You just make a wrapper function that does the cleanup. I have used this pattern many times: 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)…
I know it is just an example to illustrate the point but this seems to have a bug in it: resource2 won't be initialized if the function fail to allocate resource1 so resource2 will be null when the code enters the deallocation condition. A way to fix it would be to return different failures for every allocation and to use a switch without a break to clean up, something like: switch (ret) { case EXIT_SUCCESS: free(res…
Re: Things Rust shipped without
#135Earlier quoted context omitted.
A bitecode interpreter is another place where it's nice to have gotos. Here's the base code without gotos: typedef enum { ADD, MUL, ..., END } opcode; void run() { opcode ins; while (1) { ins = fetch_next_inst(); switch (ins) { case ADD: perform_addition(); break; case MUL: perform_multiplication(); break; ... case END: wrap_up(); return; } } } You have 3 jumps on each loop. From the break to the end of the loop, the…
That's pretty nifty, but it seems like something a really good compiler could achieve automatically. Of course I'm not sure if any compilers actually are that good.
Re: Things Rust shipped without
#136Earlier quoted context omitted.
The ability to provide a default implementation of a function in a trait that can be inherited and used by "classes" that extend that trait. In C++, this would look like: #include class B { public: int get_id() { return id; }; int id; }; class C : public B { }; int main() { C c; std::cout Maybe I'm ignorant, and there's an easy way to do this. I was screwing around with Rust a few months before 1.0 and didn't see any…
> The ability to provide a default implementation of a function in a trait that can be inherited and used by "classes" that extend that trait. Rust provides this. E.g., the "talk" method in the "Animal" trait below: [0] trait Animal { // Static method signature; `Self` refers to the implementor type fn new(name: &'static str) -> Self; // Instance methods, only signatures fn name(&self) -> &'static str; fn noise(&self…
A question (In C++ syntax, as I'm not a Rust programmer): How would one call Animal::talk inside Dog::talk? The obvious thing (commenting out the println and adding Animal::talk(self) ) causes infinite recursion. The other vaguely obvious thing ( Animal.talk(self); ) is a syntax error, which makes sense.
Edit: I'm referring to the code at the linked Rust By Example page.
Re: Things Rust shipped without
#137Re: Things Rust shipped without
#138Earlier quoted context omitted.
I've never had to use 'goto' in C++ except to break from a nested loop. In C++ labeled breaks would make 'goto' completely obsolete. In C it would still have use in the implementation of orderly error handling -- the pattern where you hand-implement exception handling in C by putting an on_error: label at the end of the function that is goto'd on error. The addition of some orderly construct for this in C would elimi…
> The addition of some orderly construct for this in C would eliminate that case, leaving no real role for goto there either. I like the way this is handled in Go with the defer keyword: https://blog.golang.org/defer-panic-and-recover This construct gives you most of the power of C++ RAII without the overhead. Except that you can't use it to cleanup resources after exiting an anonymous block—it strictly defers to fun…
Re: Things Rust shipped without
#139Rust also shipped without reflection, which was available in the beginning. I was a bit disappointed as it was something I would have made use of for serialization.
Re: Things Rust shipped without
#140Earlier quoted context omitted.
I've never had to use 'goto' in C++ except to break from a nested loop. In C++ labeled breaks would make 'goto' completely obsolete. In C it would still have use in the implementation of orderly error handling -- the pattern where you hand-implement exception handling in C by putting an on_error: label at the end of the function that is goto'd on error. The addition of some orderly construct for this in C would elimi…
A bitecode interpreter is another place where it's nice to have gotos. Here's the base code without gotos: typedef enum { ADD, MUL, ..., END } opcode; void run() { opcode ins; while (1) { ins = fetch_next_inst(); switch (ins) { case ADD: perform_addition(); break; case MUL: perform_multiplication(); break; ... case END: wrap_up(); return; } } } You have 3 jumps on each loop. From the break to the end of the loop, the…