14 ms·
Rust things I miss in C
- phkahler 9y agoOne thing jumped out for me. No integer overflow. In my embedded work we use that all the time. We represent angles as a int16_t or uint16_t where you can add and subtract angles and never have to worry about a discontinuity at 2pi because 2pi=65536. Is this a hack that should not be allowed? I don't think so. Every processor made (that I'm aware of) in the last 30+ years has used 2's complement arithmetic. I don't think overflow is a bad thing, I think C made a mistake in calling it "undefined". They had to because when the language came along there were other options fresh in peoples minds. I've also worked on systems in asm that had saturating arithmetic, and that has it's own nice use cases. My preference is still to have the rollover. People can implement bounds checking when they need to.
- heinrich5991 9y agoIn Rust, you can make your intent explicit by calling `wrapping_add` instead of using `+`.
- chewbacha 9y agoAnd here’s some documentation: https://doc.rust-lang.org/std/num/struct.Wrapping.html https://doc.rust-lang.org/std/num/struct.Wrapping.html https://doc.rust-lang.org/std/primitive.u32.html#method.wrapping_add https://doc.rust-lang.org/std/primitive.u32.html#method.wrap... :)
- tspiteri 9y agoOr if this type is used a lot, you can wrap the 16-bit integer inside its own type and overload addition and/or other operators. struct Angle(i16); impl Add for Angle { type Output = Angle; fn add(self, rhs: Angle) -> Angle { Angle(self.0.wrapping_add(rhs.0)) } }
- chewbacha 9y agoThere’s already a `Wrapping<T>` struct in std for you. I don’t think you need to roll your own. Of course, it might make sense in the embedded space to do so.
- deleted 9y ago[deleted]
- jsheard 9y agoWrapping<T> actually comes from core and is just re-exported by std, so embedded targets that lack std support can still use it by importing directly from core. https://doc.rust-lang.org/core/num/struct.Wrapping.html https://doc.rust-lang.org/core/num/struct.Wrapping.html
- chewbacha 9y agoFantastic!
- Sharlin 9y ago`Wrapping<T>` is a great solution. When in doubt, encode the behavior in the type system.
- simias 9y agoUsing 2's complement is not the entire story, some CPUs can trap on overflows (MIPS for instance). X86 doesn't but it does set the carry/overflow flags in case of unsigned/signed overlow to make it easy to test for it if necessary. Leaving the freedom to the implementation to catch signed overflows like it can catch divisions by zero might actually be a feature. Admittedly it's not very consistent to make unsigned overflow defined. I like rust's approach that you can explicitly decide to use overflowing arithmetic if you want, otherwise it triggers a runtime error in debug mode. That alongside with the checked_ variants make it very easy to deal with potentially overflowing code whereas in C it's a minefield, it's not difficult to trigger an UB while trying to defend against an other UB. Ask a beginner to write a "checked_add" function in C (no Stack Overflow allowed) and see how many bugs and UB you can spot. On the other hand advocating for implicit wrapping overflow all the time sounds risky to me. In my experience there's only a very tiny subset of operations where an overflow is desired and wouldn't lead to a bug.
- deleted 9y ago[deleted]
- VMG 9y ago> Is this a hack that should not be allowed? not by default, no
- tdbgamer 9y agoYou just have to intentionally use a method on integers called wrapping_add() to explicitly allow overflows. That said I believe overflows are only checked when you compile with the debug target. So when you compile to the release target it doesn't check them I believe. I personally think it's a good thing to only allow overflows when explicitly allowed.
- steveklabnik 9y agoThe rules are: 1. overflow is a "program error" 2. If `debug_assertions` are enabled, then overflow must panic 3. If overflow does not panic, then it must two's compliment wrap This leaves the door open to always requiring a panic someday in the future, if performance gets there.
- jacquesm 9y ago> If `debug_assertions` are enabled, then overflow must panic It is very risky to have different behavior on such things in test and production.
- steveklabnik 9y agoRust cannot fix all bugs. This isn't a memory safety issue. Sometimes, you have to make tough calls. Maybe Rust++ will fix this, someday :p (Or, once people have the tolerance for the performance degradation and we can turn it on in rustc, exactly why we specified it the way we did.) (Or, you can tweak it to include this behavior in release mode; always an option)
- jacquesm 9y agoThis is not about 'fixing all bugs', it is about re-visiting a specific class of bug that we already know about and have already seen many bad instances of in the wild. Few things are harder to debug than things that pass the tests but fail in production and anything that inserts behavior like that should be avoided like the proverbial plague. If you're already of a mindset to have a Rust++ then you are missing the point, Rust quite possibly has a window of opportunity to displace C but for that to work at a level where it succeeds rather than as an 'also ran' you will need to religiously avoid repeating the past.
- jcelerier 9y ago> Every processor made (that I'm aware of) in the last 30+ years has used 2's complement arithmetic DSPs often use saturating overflow IIRC
- phkahler 9y ago>> DSPs often use saturating overflow IIRC I've used them, and used that feature. It was an option that could be turned on and off. The basic arithmetic was the same as any other CPU unless that was enabled.
- steveklabnik 9y agoSimilar to above comments about wrapping_add, Rust has saturating_add as well.
- Symmetry 9y agoIdeally your ISA would provide adds that wrapped, adds that saturated, and adds that threw an exception on overflow.
- jwilk 9y agoTo clarify, only signed integer overflow is undefined behavior in C. Unsigned integers have wrap-around semantics. (But beware that unsigned integers smaller than int could be automatically promoted to (signed) int!)
- RealityVoid 9y agoThis should be higher up since it's a tiny but important distinction.
- chewbacha 9y ago> (But beware that unsigned integers smaller than int could be automatically promoted to (signed) int!) This caveat sounds an awful lot like undefined behavior ;p
- gpm 9y agoWhen things are promoted is well defined, just subtle behavior.
- masklinn 9y ago> One thing jumped out for me. No integer overflow. FWIW that's not quite true, Rust will panic on overflow in debug but can (and currently does on all platforms I think) allow them in release. They're not UB though, they're defined as 2's complement. > In my embedded work we use that all the time. We represent angles as a int16_t or uint16_t where you can add and subtract angles and never have to worry about a discontinuity at 2pi because 2pi=65536. > Is this a hack that should not be allowed? I don't think so. Rust provides APIs to make these behaviours explicit decisions rather than implicit hacks: https://doc.rust-lang.org/core/num/struct.Wrapping.html https://doc.rust-lang.org/core/num/struct.Wrapping.html, https://doc.rust-lang.org/std/?search=wrapping_ https://doc.rust-lang.org/std/?search=wrapping_, https://doc.rust-lang.org/std/?search=saturating_ https://doc.rust-lang.org/std/?search=saturating_ (and https://doc.rust-lang.org/std/?search=checked_ https://doc.rust-lang.org/std/?search=checked_). > People can implement bounds checking when they need to. Being unsafe by default always ends up in tears. Checking Mitre, just this year there have already been 11 public CVE for integer overflows.
- phkahler 9y agoAfter reading responses and reflecting a bit I guess rust got it mostly right. Undefined behavior is bad, so Rust defined it. Overflow is apparently a problem worth checking for. I don't understand how people are overflowing 32 and 64 bit integers, but OK it's common enough. Having the ability to declare overflow/wraparound as being OK is a good thing so long as it compiles down to the same add or subtract instruction and doesn't add overhead. Rust claims to have zero overhead abstractions, so I'll have to try this some day. TL;DR the decisions made in the design of Rust seem reasonable.
- steveklabnik 9y agohttps://play.rust-lang.org/?gist=5b5df368283645fbec18c4fbaeb3c960&version=stable https://play.rust-lang.org/?gist=5b5df368283645fbec18c4fbaeb... Click "release" and then "asm", you'll see that they are compiled to the exact same thing.
- woolvalley 9y agoYou can overflow 32bit integers fairly easily if your doing math with unix epoch microseconds.
- carlmr 9y agoI'm also working in embedded, and you're picking one of the few examples where you want wrapping behavior. So it's better IMHO to do it the Rust way and only allow wrapping with the Wrapping<T> type. That way you can see where wrapping is part of the program design.
- vbarrielle 9y ago> We represent angles as a int16_t or uint16_t where you can add and subtract angles and never have to worry about a discontinuity at 2pi because 2pi=65536. Not sure I get your trick, 2pi=6.2832 so I don't see how you avoid accumulating errors this way.
- Sean1708 9y agoIt's basically fixed-point arithmetic[0] applied to base tau. So any integer value x that your computer is actually storing is conceptually the value 2 * pi * x / 65536. [0]: https://en.wikipedia.org/wiki/Fixed-point_arithmetic https://en.wikipedia.org/wiki/Fixed-point_arithmetic
- mattkrause 9y agoYou don’t use the value directly. Instead, divide the circle up so that there are 65535 steps around the unit circle between [0, 2*pi) and use these units instead of degrees or radians. This makes integer overflow and wrapping around the circle correspond: going a quarter way around the circle five times, adds up to 90 degrees, rather than 450.
- badpun 9y agoThis is pretty awesome little trick, thanks!
- marcosdumay 9y ago> Is this a hack that should not be allowed? Yep. This is a hack that should not be allowed. If yo want to use it, you should create your own type, with explicit modular arithmetic. Not try to ride architectural dependent assumptions.
- myrrlyn 9y agoFwiw, Rust provides checked_op, saturating_op, and wrapping_op versions of arithmetic, as well as a Wrapping … wrapper https://doc.rust-lang.org/std/num/struct.Wrapping.html https://doc.rust-lang.org/std/num/struct.Wrapping.html
- hsivonen 9y agoRust has all these arithmetic modes on its integer primitives. The operators, such as +, panic on overflow in debug buids and wrap as two's complement in release builds. As methods you get: 1) Two's complement wrapping (even in debug builds) 2) Saturation 3) Overflow checking (these return Option<T>
- masklinn 9y ago> 1) Two's complement wrapping (even in debug builds) As it's a relatively common need, there's also a wrapper struct for this one: https://doc.rust-lang.org/core/num/struct.Wrapping.html https://doc.rust-lang.org/core/num/struct.Wrapping.html
- quelsolaar 9y agoI agree, Overflow is useful and it reflects how the hardware works, so its not something you want to emulate with modulo. The mistake of the C standard was not having it "Platform dependent", rather then "Undefined". The difference is a big deal. Since overflow is undefined the optimizer is allowed to assume it never happens and therefor optimize away things, even though the behavior is defined on all CPUs known to man.
- gpderetta 9y agounsigned overflow is well defined in C.
- pjc50 9y agoIt should be "allowed", but not by default in normal arithmetic. This has cost Etherum developers and their victims a lot of money e.g.: https://github.com/ethereum/solidity/issues/796 https://github.com/ethereum/solidity/issues/796 Ideally you'd be able to specify which mechanism you wanted for arithmetic as a property of a type, so you could have int_saturating and int_wraparound and int_nooverflow in the same code with the compiler preventing you from combining them by mistake. C made it undefined because at the time of its manufacture twos-complement had not quite comprehensively won. There were still a few ones-complement systems in the 80s. https://en.wikipedia.org/wiki/UNIVAC_1100/2200_series https://en.wikipedia.org/wiki/UNIVAC_1100/2200_series
- sureaboutthis 9y agoIt seems to me he, first, talks about all the wonderful code he has seen written in C, then complains about C when he runs into terribly written C code but wants to blame it on C. I have a problem with that. He then concludes that he likes things about Rust but then states Rust is a lot harder to learn but you become a better programmer cause you have to work harder on it. But isn't that what he complains about with C?
- tdbgamer 9y agoUhh did you read the same article I did? 90% of the article was features missing in C: Generics, Slices, Dependency Management, Tests, Useful macros, Pattern matching, etc. Those things have nothing to do with good or bad code and have everything to do with the language.
- sureaboutthis 9y agoDid you read the first section of the same article I did? You seem to have skipped that part.
- tdbgamer 9y agoHe mentioned some bad C experiences he had for a whole 7 sentences and that's your take away from the article? You're totally missing the point dude. The point is that C doesn't protect developers from some of the most basic mistakes and offers very little tooling compared to modern languages. It turns out that maintaining huge software projects in C is actually really hard.
- lmm 9y ago> He then concludes that he likes things about Rust but then states Rust is a lot harder to learn but you become a better programmer cause you have to work harder on it. But isn't that what he complains about with C? The difference is that when you haven't learned/aren't good enough in C, you'll make a codebase that sort-of works for now but is buggy and unmaintainable - code that reads uninitialized values or never free()s or works as an application but could never be turned into a library - whereas in Rust your code won't compile until you get good enough to write it properly.
- andrepd 9y agoI would just like to point out that many of these features are also features of C++ :)(RAII, Templates, etc.).
- tdbgamer 9y agoC++ does have a lot of the features that Rust has. You won't get any of the memory safety guarantees or compile time checks though. I will say that to me a lot of the C++ equivalents to Rust features seem very awkward to use (maybe not once you're used to C++ I guess). This guy does a pretty good presentation on Polymorphism in Rust vs C++: https://www.youtube.com/watch?v=VSlBhAOLtFA https://www.youtube.com/watch?v=VSlBhAOLtFA
- pjmlp 9y agoThe major issue with C++, is what also helped the language gain market adoption, copy-paste compatibility with most of C89 code. So security conscious C++ developers tend to use enum class, string, vector and array classes, RAII, iostreams, wrapping data access in classes with invariants,... Developers with more C oriented mindset, tend to just code away like "C with C++ compiler" programming style. Hence the need being discussing since the last three CppCon, to stop using C style programming in modern C++. CppCon 2015: Kate Gregory “Stop Teaching C" - https://www.youtube.com/watch?v=YnWhqhNdYyk https://www.youtube.com/watch?v=YnWhqhNdYyk CppCon 2015: Bjarne Stroustrup “Writing Good C++14” - https://www.youtube.com/watch?v=1OEu9C51K2A https://www.youtube.com/watch?v=1OEu9C51K2A CppCon 2017: Bjarne Stroustrup “Learning and Teaching Modern C++” - https://www.youtube.com/watch?v=fX2W3nNjJIo&t=2s https://www.youtube.com/watch?v=fX2W3nNjJIo&t=2s Of course, preventing copy-paste compatibility with C, already solves many of those issues from the get go.
- jacquesm 9y ago> Developers with more C oriented mindset, tend to just code away like "C with C++ compiler" programming style. The way I've seen it described is 'C with more convenient comments'.
- adwhit 9y agoFor more detail into the porting effort, I recommend taking a look at these slides, taken from a talk the author gave last year: https://people.gnome.org/~federico/blog/docs/fmq-porting-c-to-rust.pdf https://people.gnome.org/~federico/blog/docs/fmq-porting-c-t... "Rust revived my interest in maintainership. It is very empowering to finally have a good language that I can use at the level of the stack where I work."
- peterwwillis 9y ago> You don't have to fight dependencies. It just works when you cargo build. Unless you're using caret requirements, or tilde requirements, or wildcard requirements, or inequality requirements, or multiple version requirements, or dependency overrides. By default, Rust, much like every other language I know of, does not require explicit versions or checksums for dependencies. This means it's up to the developer to work really hard to make sure their code will actually work as expected outside of their own build environment. This could be mostly avoided if more people used explicit version requirements in their code, but nobody seems to want to do this (which is strange, because your code is what needs specific deps, so why not keep the version requirements right there?) edit: For all the duplicate comments mentioning cargo.lock: The official FAQ details how libraries do not impose requirements at build time (https://doc.rust-lang.org/cargo/faq.html#why-do-binaries-have-cargolock-in-version-control-but-not-libraries https://doc.rust-lang.org/cargo/faq.html#why-do-binaries-hav...): "Users dependent on the library will not inspect the library’s Cargo.lock (even if it exists)". The user cannot be certain their app will always work, because they can't be certain that their dependent library has been tested on each other library dependency. Basically, there's no certainty if you use libraries. The other thing people are missing is how being able to call duplicate conflicting versions of the same library where it is needed in your code would allow you to work around complicated bugs in large projects automatically, rather than having to find a magic combination of conflicting dep versions that work for your app and its dependencies. Apparently nobody here has ever tried to manage more than one OpenStack tools tree for use by the same application.
- K0nserv 9y agoCaret, tilde and other loose requirements are fine in Cargo.toml because cargo generates Cargo.lock on your behalf with the exact versions required for your build. This is how pretty much all modern dependency managers work(Bundler, Composer, NPM, CocoaPods, SPM, etc). Saying that this doesn't work just is not true.
- Liquid_Fire 9y agoAll you have to do is keep your Cargo.lock file in version control, and you will have consistent dependency versions in any environment. This will work regardless of how generally you specify the version requirements of your dependencies.
- bluejekyll 9y agoTIL: How about this instead, with pattern matching on function arguments. I didn’t know you could do that. I might need to go back and see what I can simplify with that trick.
- arcticbull 9y agoI’ve used param structures with destructuring where things got too messy. I wish they’d add optional named parameters as first class one of these days.
- whyever 9y agoOptional parameters are tricky because of type inference. See this tracking issue: https://github.com/rust-lang/rfcs/issues/323 https://github.com/rust-lang/rfcs/issues/323
- deleted 9y ago[deleted]
- deleted 9y ago[deleted]
- dilatedmind 9y agoI just installed rustc to test this example, turns out you cannot do pattern matching on function arguments like you can in erlang. note: `my_func` must be defined only once in the value namespace of this module
- piinbinary 9y agoIt might be more accurate to call what Rust can do to function arguments "destructuring" rather than "pattern matching"
- steveklabnik 9y agoDestructuring is a feature of pattern matching, so yeah, this is slightly more specific. I don't think "pattern matching" is incorrect, though.
- gameswithgo 9y agoI tried to do a small project using Rust and SDL2 and gave up due to having to deal with lifetimes on textures. > you just implement the [Drop] trait and that's basically it. Is that what I was missing? could I have done that and not had to deal with lifetimes?
- arcticbull 9y agoLifetimes can be a challenge to learn but once you do not having to worry about whether something is actually getting destroyed is a great feeling. The opposite example is I just wrote some GL in Swift and I have no idea if my GL textures are leaking. I’m confident with lifetimes I’d know ^_^ my email is in my profile. Happy to help out if you’re still interested in debugging.
- thibran 9y agoYou always have to "deal" with lifetimes. The rules are not that complicated once you understand them. It boils down to: * An object can only have one owner. * When giving a reference away from an object, the reference has a lifetime that makes sure the reference doesn't outlive the owner. * You can either have one mutable reference >>or<< arbitrary read-only references. * An owned object must be denoted mutable to be mutable, otherwise it is read-only.
- grok2 9y agoSome comments with the caveat that I have used Rust only for a short learning exercise a while ago and I don't fully understand programming in Rust (and found it tough going), but I think the problem is not about being able to understand the ownership models and lifetimes (which seems fairly straightforward conceptually). The problem is in being able to put together a program that the compiler does not complain about. It always seems like you have to "feel" your way around by trying different things like a jigsaw puzzle rather than having a "canonical" way to do things that fit the lifetime/ownership model. Maybe there are more canonical ways based on people's experiences nowadays and maybe this problem is due to approaching solving things using a C (or other language) mind-set. It seems like learning these ways to avoid the Rust compilers errors related to lifetimes in any complex program takes longer than in other languages.
- hzhou321 9y agoIt might be off topic but I just had this thought and like to write down… If you treat your program (and your problem) as math, then it is necessary to explicitly define all its boundaries. However many (most) problems in real life are not strictly math problems due to their nature of ambiguity. The ambiguity has its physical source of unknown boundaries. For example, you may think you only need 32-bit integer and you may be sure of it today, but your assessment may change in the future. Similarly, you may think today you should use arbitrary precision and the constant boundary check does not matter, but it may matter some day. In the effort to eliminate undefined behavior, we are projecting our ideas from real world onto math realm. That projection may be quite lossy. I am aware that the actual compiled program is always well defined and can be a perfect mathematical object, but it's source as a language do have ambiguity -- e.g. compiler implementations and undefined behavior. Ambiguous language sometimes can express ideas better than a mathematical language -- if we treat the legacy of our code more in its source rather than in its binary.
- jjgreen 9y agoI found the first point on unit-testing of C odd, I always treat static functions as implementation details and test only the public interface. CUnit is nice enough (if a bit long in the tooth).
- woogley 9y agoThere's a culture of testers who believe 100% code coverage is important enough to include "private" implementations, and will happily break encapsulation rules for sake of hitting 100% coverage.
- jjgreen 9y agoIf things are really gnarly in the implementation, one can always break it up into submodules to expose that functionality as public (and that's usually good architecturally IMHO).
- zbentley 9y agoEh, I think both extremes are sub-optimal. Some small public APIs are backed by large enough implementations that it pays off to be able to test implementation details. Sure, it might be "poorly factored" code that should have a bigger API and smaller guts, but that's not always an something you can change. Also, writing tests for internal behavior before refactoring can give you a good blueprint for how the refactored code should behave--being able to read the tests to specify unclear behavior is, while far from enjoyable in some cases, better than nothing. You're right that there are some pretty silly test suites that break encapsulation for a coverage number without actually testing anything useful, though. I don't think an absolute "all tests must behave thus" rule (e.g. coverage requirements, "only test public functionality", "refactor the instant something isn't easily testable") is useful. Explain the benefits of each path, and make sure the decision of what compromise to make--and in any project more than a one-developer hobby, you will have to compromise here eventually--is in the hands of people with the experience and common sense to make the right one.
- newnewpdro 9y agoIt's fairly trivial to have every listing contain a main() gated on a testing ifdef which may call the local static functions. In essence every .c listing becomes a test program.
- chucksmash 9y agoTangential, but if you're looking for a project to do as you learn Rust, there's an ongoing Operating Systems class being taught at Stanford in Rust right now[1]. The "Ferris Wheel" portion of assignment #1 was particularly useful for language knowledge; 25 source files which you must make compile/not compile/pass tests (along the lines of the Ruby/Kotlin Koans), along with a test harness you can run locally. [1]: https://web.stanford.edu/class/cs140e/syllabus/ https://web.stanford.edu/class/cs140e/syllabus/
- eduren 9y agoI'm definitely interested in giving it a try. Do you know if the Pi kit they are using is sold as a complete package somewhere? I found a list of components in the Assignment 0 description, but that's it.
- chucksmash 9y agoBought a Pi 3 starter kit from a local place near me. It came with: - Raspberry Pi 3 - 1⁄2-sized breadboard - 4GiB microSD card - microSD card USB adapter - CP2102 USB TTL adapter w/4 jumper cables - 10 female-male DuPont jumper cables And I had to buy: - 10 multicolored LEDs - 4 100 ohm resistors - 4 1k ohm resistors - 10 male-male DuPont jumper cables Specifically this kit: http://tinkersphere.com/raspberry-pi-orange-pi-boards/1538-raspberry-pi-3-starter-kit-raspberry-pi-included.html http://tinkersphere.com/raspberry-pi-orange-pi-boards/1538-r...
- kzrdude 9y agoI think that C would have lasted us much longer if it just had C++-style templates. No classes, exceptions or other C++ features needed.
- Retra 9y agoCan't macros already do everything templates can? I mean, it would be nicer to have templates, but I don't see why that would be a bottleneck for anything. Someone could probably write a templating macro and you could use that to the same effect.
- kzrdude 9y agoI've seen that many times, written a few of them, and it's pretty horrible. Real templates are needed for such basics as generic data structures.
- oconnor663 9y agoI think the other critical feature you need is destructors, before you can build really helpful containers.
- dcow 9y ago> Rust generates documentation from comments in Markdown syntax. Code in the docs gets run as tests. You can illustrate how a function is used and test it at the same time: /// Multiples the specified number by two /// /// ``` /// assert_eq!(multiply_by_two(5), 10); /// ``` fn multiply_by_two(x: i32) -> i32 { x * 2 } Okay that's pretty cool.
- ndh2 9y agoPython has that as well: https://docs.python.org/3/library/doctest.html https://docs.python.org/3/library/doctest.html
- bmn__ 9y agoPerl has that as well: http://p3rl.org/Test::Inline http://p3rl.org/Test::Inline
- theshrike79 9y agoGodoc does this too
- Lev1a 9y agoConcerning the "Pattern matching" section, I've never, in all my time programming Rust, seen that specific pattern of destructuring the input values of the function in the fn declaration part. Now I feel the need to use that everywhere...
- steveklabnik 9y agoA lot of people didn't know! I made sure to put it in the book explicitly: https://doc.rust-lang.org/book/second-edition/ch18-01-all-the-places-for-patterns.html#function-parameters https://doc.rust-lang.org/book/second-edition/ch18-01-all-th...
- Lev1a 9y agoHuh, was that also in the first edition? I learned using that and if this pattern matching pattern (heh) is indeed in there, I must have overread it...
- steveklabnik 9y agoI’m not sure, to be honest, it’s been a long time!
- vatotemking 9y agoMy favorite thing in rust is the error handling and propagation. Using JS for comparison. Example, this code in JS function decode(path){ try { return parse(path); } catch (err){ throw err; // rethrow } } Could be compacted into this using try! macro or "?". pub fn decode(path: &File) -> Result<Image>{ try!(parse(path)) } For error propagation, I could easily consume the error of a third-party lib, and convert it into my own using the From trait: /// Convert std::io::Error to RasterError::Io impl From<IoError> for RasterError { fn from(err: IoError) -> RasterError { RasterError::Io(err) } } Where as in JS, I would have to write a lot of if else if I want to convert a third-party package's error into my own error. if( error.name === "IoError" ){ let err = new Error(error); err.name = "MyError"; return err; } else if (...) ... }
- steveklabnik 9y agoDon't forget that try! turned into ? so that's now parse(path)? !
- vatotemking 9y agoYes but I still prefer try! as its easier to see (personal preference)
- colejohnson66 9y agoWhat’s the point of catching and rethrowing?
- vatotemking 9y agoWhen your inside a module and you want the app using your module to catch the exception.
- v_lisivka 9y agoI'm working on library to bring some Rust features back into C, like semiautomatic memory management (defer), Vec, Slice, String, Str, Option, built-in test cases, generics. But I lost interest because I'm allowed to use Rust in embedded project now. :-) https://github.com/vlisivka/crust https://github.com/vlisivka/crust
- sitkack 9y agoThank God!
- ndh2 9y ago> Some good experiences with C > Reading the POV-Ray code source code for the first time and learning how to do object orientation and inheritance in C. But https://github.com/POV-Ray/povray https://github.com/POV-Ray/povray is all C++... It even says "Written in C++" on the Wikipedia page. Was he talking about some other source, maybe some older version? Edit: [1] Here is a discussion about this topic from 2012. It seems that POV-Ray was ported to C++ for version 3.7. [1] http://news.povray.org/povray.programming/thread/%3Cweb.4f01ba3c6f2bacd09be4b6d10%40news.povray.org%3E/ http://news.povray.org/povray.programming/thread/%3Cweb.4f01...
- peternicky 9y agoEnjoyed this article so much.