Hacker News new | ask | show | jobs
by fungos 3443 days ago
Just for fun, really, I've done a Result impl in my lab code[1]. I'm willing to improve it just to see how far I can get with it. :)

The next improvements will be custom error types (I had it done but reverted in this code) and a error_chain like feature (started testing and forgot to remove some not working code there).

[1] https://github.com/fungos/sllab/blob/master/src/viewer.cpp#L...

1 comments

Thanks for this.

I don't fully understand your code yet: Is it the case that the type-safety of your approach relies on the caller honouring the convention of accessing Result<T,E> via the try and try_chain macros?

I really need to look in detail at how Rust enforces type-safety of Result<T,E>. One thing that I like about how algebraic data types work in functional languages (e.g. Either in Haskell) is that they eliminate entirely the need for null pointers completely and the possibility of derefencing them (Tony Hoare's billion dollar mistake) and I had assumed that Rust would give me the same.

The type safety of my sample is based on the auto deduction of the types at compile time.

You can see somewhere there I do this:

  return std::move(ArgsResult Ok(options));
I could also have done:

  ArgsResult func() { ... return Ok(options); }
In this example there are two instantiations of the type Result<T, E>:

  typedef Result<ProgramOptions, Error> ArgsResult;
  typedef Result<bool, Error> ProgramResult;
(Note that the typedefs aren't needed, but I prefer to be explicit there.)

The try macro is just trying to emulate try! and it is not really needed. We may access the result by hand and the correct type will be used, but it is way uglier (see: https://github.com/fungos/sllab/blob/master/src/viewer.cpp#L...) due the access on the struct members .e (error) or .v (value). And if I try to assign .v to another type, the compiler will give a compile time error.

And probably would be better to use std::variant there as it is more like a tagged union, I just haven't tried to improve on it anymore.

Also, note that my unwrap doesn't panic, I should put a test/assert there...

Anyway, the poc is there and it should possible to have something almost as clean as Rust with some more work.

> I really need to look in detail at how Rust enforces type-safety of Result<T,E>.

Basically, you can't use it as a T or an E; you have to process it in some way first. Basically, if you're familiar with Either, you know the whole story, it is the same. We originally had Either, then someone made Result, people always reached for Result over Either, so at some point, we axed Either. There is https://crates.io/crates/either though too.

Result is exactly Haskell's Either, just with a different name.

> I had assumed that Rust would give me the same

They do. ADTs in Rust are very similar to languages like Haskell. The only major difference I can think of is everything is stored inline in the enums in Rust (they're what one might call "value types" in some languages) without any allocations required.