Hacker News new | ask | show | jobs
by alphaalpha101 3218 days ago
Personally I loathe this style of programming. It's not that it's difficult, it just seems to obscure code a great deal.

Writing this sort of thing in Rust:

    fun some_function(a: &A) -> Result<&B, SomeError> {
        let c = foo(a)?;
        let d = foobar(a, c)?;
        Ok(if xfoo(c) {
            let e = blah()?;
            bar(d, e)?
        } else {
            baz(d)?
        })
    }
where you have to write every function in this pseudo-do-notation where 'return' is just wrapping the return expression in 'Ok' and `a <- expr` becomes `let a = expr?;` is just horrible.

I'd much rather write this:

    fun some_function(a: &A) -> &B throws SomeError {
        let c = foo(a);
        let d = foobar(a, c);
        if xfoo(c) {
            let e = blah();
            bar(d, e)
        } else {
            baz(d)
        }
     }
See how that's so much cleaner? It's not actually any different from exceptions anyway, you're basically using them like exceptions, and they're implemented in the same way. The difference is that in the latter the code is much simpler and easier to understand. That's all.

In fact, that syntax could be added to Rust (after 6-12 months of bikeshedding as usual) and just have it automatically translated to the above anyway.

The other issue with Result/Option is that people start doing really horrible things like adding Option::map. Sorry but it's not a container that has 0 or 1 things in it. It's an optional value. That they're mathematically equivalent doesn't mean that they're the same thing conceptually. It's as bad as pretending that Result<T, Err> is useless and everyone only needs Either<L, R> where by convention R is the error value. God please just no.

1 comments

> See how that's so much cleaner?

No, I don't. I look at the former snippet and I can easily tell each and every function invocation that can cause SomeError. In your theoretical style, I have no idea whether foo, foobar, xfoo, bla, bar and/or baz will throw that error. I prefer explicit over implicit since I find it far more readable.

> really horrible things like adding Option::map

You can quibble about the names (Option and map), but Option is essentially the Maybe monad and map is bind, so you're kinda arguing against core functional programing constructs.

>No, I don't. I look at the former snippet and I can easily tell each and every function invocation that can cause SomeError.

The reason that functions have type signatures is that you can read them. You can tell which functions can cause SomeError by going and reading their definitions.

>I prefer explicit over implicit since I find it far more readable.

'Explicit over implicit' is dogma. Rust requires you to annotate your code with gibberish in cases where it is not necessary.

>You can quibble about the names (Option and map), but Option is essentially the Maybe monad and map is bind, so you're kinda arguing against core functional programing constructs.

That's literally my entire point. The attitude that it's technically a Functor so it makes sense for it to be called map? No, it doesn't. It's not a map. You're not mapping over anything. Naming is important.

Calling it 'the Maybe monad' shows that you actually have no idea what you are talking about. It's not 'the Maybe monad'. The Maybe monad is the instance of Monad for Maybe. It is not Maybe itself.

The entire concept of having the literal 'Monad' word as a word in your language, a thing that you use in programming, is very stupid. Monad is not a useful or good abstraction. Maybe is a good abstraction. Or Optional, or Option, or whatever you decide to call it. But Monad is a bad abstraction. Abstracting over superficial syntactic similarities between completely different constructs is completely stupid.

The name being terrible is not 'quibbling' by the way. Naming is incredibly important. Calling it 'map' just shows how out of touch Rust is with real programmers.