Hacker News new | ask | show | jobs
by nextaccountic 1404 days ago
Does C++23 have something like Rust's ? for std::expected?
3 comments

It’s extremely non-obvious how to do the Maybe and Either type classes in C++ in a truly ergonomic way.

Rust wiring in syntax for this (which is what ?-notation is, it’s special-case do-notation) is both a blessing and a curse: it’s extremely useful today and a breath of fresh air relative to C++ or Java or whatever but this scenario has been seen before: GHC had do-notation and return, which are dramatically more flexible than ?-notation, wired in pretty deep when people started realizing that you want Functor => Applicative => Monad with pure === return and ApplicativeDo. They’re still trying to get the migration done today and they started years and years ago.

Time will tell how Rust will age as it inevitably continues adding algebraic power, but superficially ?-notation seems doomed to end up a kind of dangling appendage that will be obsoleted by some more general notation for algebraic effects.

That's interesting. Having learned Haskell long before Rust (and having been programming in C++ for a long time) I found Rust's ?-notation to be annoyingly limited due to the reasons you gave, and also annoying syntactically. I saw in many Rust sources it's often tucked away at the end of lines, flush against the last character, a single character which changes the meaning of the line, well, the whole function, but is often lost to me visually, and I have to scan the line to see it. But I guess people got used to it or just don't bother parsing all characters in a line of code like I do.

When you say "They’re still trying to get the migration done today... " you mean Rust's core developers, right? Is there anywhere I can read up on it?

Ah no the migration I was referring to is `Applicative`: I just upgraded our "primary" Nix `devShell` to use `9.2.4` (`RecordDotSyntax` is finally here, may the thousand-year reign of the Glorious Glasgow Haskell Compiler commence! /s) and it's hitting me with deprecation notices about `return = ...` rather than `return = pure` and/or omitting and explicit `return`. Which makes sense, the rationale is at https://gitlab.haskell.org/ghc/ghc/-/wikis/proposal/monad-of....

I remember when I was working on `Haxl` at FB in like, 2015 or 2016, it needed `ApplicativeDo` and that was like, quite the novelty in industrial Haskell (I think it was already a no-brainer to the research/OSS/etc. crowd). So mainstreaming `Applicative` into the effects hierarchy has been going on for 6 or 7 years that I know about, and I bet a lot longer than that (the paper introducing `Applicative` is from 2008: https://www.staff.city.ac.uk/~ross/papers/Applicative.html).

There's an (admittedly oversimplified) sales deck for algebraic effects that I have found really effective at selling this stuff to open-minded non-FP hackers: https://philipnilsson.github.io/Badness10k/posts/2017-05-07-....

At the risk of inviting an old-fashioned HN brigade gang-tackle: I think it indirectly illustrates why Rust is going to end up going all-in and ditching the ?-notation. Please don't hurt me.

There is ongoing work to generalise ? operator in Rust with traits[1]. If it succeeds, current code is not going to be obsoleted by the new solution, only extended.

[1]: <https://doc.rust-lang.org/std/ops/trait.Try.html>

If compound statements every get standardized then you could write a TRY macro that worked pretty similarly.

https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

Yes we've been using this. Unfortunately it is not standard and iiuc msvc has no equivalent?
Exceptions.
Exceptions are nothing like Rust's Result.

- exceptions don't appear in the signature of a function

- you don't have to handle exceptions explicitly, while you cannot access the value of a Result without explicit error handling

- Exceptions are implemented like Rust's panic. The error path in exception is more costly, while the nominal path is supposedly less so, due to less register and branch pressure than the result type that at least has a discriminant to check.

Exceptions are such a different way or handling errors from Result that my team finds itself reimplementing Result types in C++ again and again. Alas, it is neither standard nor ergonomic in C++