7 ms·
I am not that familiar with Rust, however every time I see it I am more and more impressed. One thing that I don't see here but which I think it might be impor
by benjaminjackman 12y ago
I am not that familiar with Rust, however every time I see it I am more and more impressed.
One thing that I don't see here but which I think it might be important is to grab the stack trace in the failure, or atleast the Filename / Line Number of where each Err is allocated. It will be really useful to be able to see the details for figuring out what went wrong, and following the stack trace is very important. With that I think the abstraction is 99%+ superior to exceptions, which is quite a step forward for the programming craft.
What really has to be guarded against though is that a lot of functions are going either have function signature that is much more verbose which leads programmers `cheating` and just `swallowing` the error by forcing the result out -OR- Return type inference might save the day (not sure if Rust has return type inference of not), however it doesn't solve everything, writing the return types on public functions pretty quickly becomes standard operating procedure, and then programmers are going to get lazy again and we are right back at checked exceptions `polluting` their interfaces and they might not want to deal with it.
interface Perfect {
def foo : Foo
def bar : Bar
}
interface NotPerfect {
def foo : Result[Foo, FooErr]
def bar : Result[Bar, BarErr]
}
Which of these do I implement first? Does the type system allow me to substitute a Perfect when a NotPerfect is required, or do I have to re-teach it every single time, that in fact, it's totally ok to do so (make a method `perfectCanBeUsedForNotPerfect(p : Perfect) : NotPerfect = new NotPerfect ....)`? Can I fix the issue for a limited set of cases and declare that Perfect implements NotPerfect and is therefore a subtype? Can I do similarly if I implement NotPerfect after Perfect was implemented (add an implicit conversion from Perfect to NotPerfect)? Can I just avoid the whole problem all-together with by-name subtyping (aka Point3{x,y,z} is considered a subtype of Point2{x,y} because Point3 has all the same named fields as Point2 with an extra one added) and informing the type system of the fact that Foo is a valid substitution for Result[Foo,_] because Result[A,B <: Err] is a type-disjunction of A | B and type-disjunction allows for substitution by the disjoint types? Where is Rust going to fall on this continuum and how many programmer hours is going to waste for each and every one of them to teach the its type-system over and over and over these simple patterns via boilerplate code?
We static programmers will grumble on regardless, we pay our dues to the type checker because we believe its gives us structure and forces failure when while we write the code, not because we want to write boilerplate to teach it simple facts.
...
All in all this is really cool. From a Scala perspective it's a much improved version of Either (and now Try), and it's going to be supported by the standard library in Rust. Which is awesome.
Either itself basically is Scala saying, we don't have type disjuction, so here is a disjunction of 2 types which we will call Left and Right. And by convention Left is used to hold the error condition.
Because no one could remember that Left by convention meant error, and because it would by nice to gussy up what is held in the error type by having your errors be able to point a source error, Scala then later added a Try disjunction. Which is composed of two types Success[A](a:A) and Failure(e : Throwable).
The Success part is fine it's hard to mess that part up, it's just like Ok, having a uniform this just a wrapper around another type would be nice but, we suck that down as programmer business as usual, the Failure side however leaves a lot to be desired, by DESIGN the failure side cannot hold a failure and instead has to hold an exception, this is wrong, failure is a failure. Given the runtime on which Scala runs, the JVM, ignoring exceptions all-together is probably a worse evil. However it should have been made a special subcase of the Failure subclass rather than the only thing it can contain, or Try itself should have been the sub-implemenation of some more generic structure.
What to add a custom message to your failure? Ok make an exception that has a message in it.
Want to pass a Failure up the chain while adding your own error message for context? Ok make an exception then add the failure into it.
Want to fail without an exception? Ok make an exception and put it in the Failure.
Looks like Rust is moving towards a great implementation. This is something that has to be done in the standard library and has to be done well. The more I see of Rust as a language the more impressed I am, when is Rust going to compile to Javascript, oh never I see[1], well back to my ScalaJS cave then :)
1:https://news.ycombinator.com/item?id=4630403 https://news.ycombinator.com/item?id=4630403
- kibwen 12y ago> not sure if Rust has return type inference of not Rust has return type inference for function invocations, but not for function signatures. This is a conscious decision to force all functions to provide an explicit contract rather than having any global type inference. And really, I wouldn't want function return types to be completely inferred in Rust given its last-semicolon rule. However, there is an RFC that would allow for "abstract return types", which would let a function state that its return type implements a certain trait and allow the programmer to omit the concrete type. This is somewhat essential for the new closure design, and also greatly benefits functions that return iterators (but it might not be relevant to your question at all, I haven't had my tea yet...). https://github.com/rust-lang/rfcs/pull/105/files https://github.com/rust-lang/rfcs/pull/105/files > when is Rust going to compile to Javascript Never officially, but that doesn't mean an Emscripten backend isn't possible https://github.com/rust-lang/rust/issues/2235 https://github.com/rust-lang/rust/issues/2235 :)
- steveklabnik 12y agoRust used to also have Either, and it was changed to Result for the same reasons. Name things what they mean. :)
- kibwen 12y agoFunnily enough, we actually used to have both Either and Result, until one day we went through and realized that no code in existence was using Either and decided to go all-in on Result instead.
- steveklabnik 12y agoSomeday, we should have a "History of Rust" thing, kinda like folklore.org or something.
- Chris_Newton 12y agoStroustrup’s The Design and Evolution of C++ is a fascinating case study of trying to create a good programming language in the real world. I suspect that, once Rust has stabilised and the dust has settled, a retrospective from key contributors in a similar style would also make very interesting reading. I’m sure I’m not the only one following along and looking forward to 1.0 but not necessarily keeping up with the day-to-day decisions and all the detailed debate as the language evolves.