News for hackers. Stuff that matters.
Re:Rust and the Blub Paradox by saurik on Saturday January 23, 2016 @12:57PM (#10959204)
I think "blub" is relative. I look at people who think that cluttering code with boilerplate for error handling, and even those who think that boilerplate is sufficient is sufficiently papered over using macros, have yet to understand why exceptions are interesting or (often) how to use them correctly (as many uses of exceptions that people like to poke at are entrenched wrongness, much like how many people who hate the entire idea of relational databases really just hate MySQL, its limitations, and the attitude of its ecosystem). I feel one of the reasons I have been as productive as I have been over the years is that I have spent a lot of time studying error handling and even now have a sort of "theory of errors" that I will sometimes draw out for people on a blackboard. From my perspective, Rust is currently "unusable", though very compelling and will hopefully fix this problem. As much as I agree with other things it has built, and as much as I agree that my attempts to simulate those things in other languages have disappointing holes, after having spent a lot of time studying languages like Erlang and Haskell (and even as someone who teaches a class at a college on programming languages at the college level), not having exceptions or anything better than try! is a deal breaker for me, and while this person jokes about monads and how learning them might not be important, they would be well served learning why monads are interesting. One could even argue the entire section about error handling and how this developer is happy about how "straightforward" Rust is in comparison to monads is the "blub" issue rearing its head, but between Rust and Haskell. (The use of the word "straightforward" is always particularly concerning to me, as it is the general argument one uses for programming in C or Java instead of anything that hides intent.)
Re:Rust and the Blub Paradox by pcwalton on Saturday January 23, 2016 @01:35PM (#10959359)
Rust's error handling is, empirically, not unusable. I use it every day.

Even Go's error handling clearly isn't unusable, as controversial as it is, and try! is pretty much just a more sugary version of it.

Also, we were well aware of monads when we designed the Rust error handling system and in particular why they do not work very well in languages that have rich, imperative control flow structures. try! is basically just monads for imperative languages. To see this, work through what happens if you try to add break/continue/return to Haskell's system.

Re:Rust and the Blub Paradox by steveklabnik on Saturday January 23, 2016 @02:00PM (#10959513)
I still don't fully understand the break/continue/return argument, at all. I should bug someone to actually write this up.
Re:Rust and the Blub Paradox by pcwalton on Saturday January 23, 2016 @02:15PM (#10959579)
An oversimplified version: the monad rules/type signature only allow for possibly-recursive sequences of statements. That admits straight-line code as well as if, while, and for. But it doesn't allow for any exceptional loop exits (more formally, doesn't allow for any backwards edge from node A to B unless A postdominates B).

There are ways to transform code to allow this to work (there has to be, since Haskell is Turing-complete), but it's not straightforward.

Re:Rust and the Blub Paradox by steveklabnik on Saturday January 23, 2016 @02:27PM (#10959650)
I guess I'm just not sure why this is a problem, exactly. Even if you couldn't use those statements inside of a `do` block, that shouldn't be an issue? Just like using `break` outside of a loop is invalid, it would be the same here.

The Option monad already is a sort of early return. Inside of monadic combinators, you use the monad for control flow instead of those statements. Seems fine to me, though admittedly my Type Theory Wizardry isn't the strongest.

Re:Rust and the Blub Paradox by pcwalton on Saturday January 23, 2016 @02:35PM (#10959686)
do is only really good if you use it for the whole function, or at least have some way to get the error out of the do block to the code that's supposed to handle it. But if break isn't allowed inside a do block, then if you need to break you have to split up your do blocks into blocks before the break and after the break. Now if there's an error thrown by one of the statements in one of those do blocks, then you have no straightforward way to propagate it out of the function. You would need to pattern match on the result of each do block and return the error if there was one--in other words, you would need to write try!

This is why I called try! monads for imperative languages: the early return that is expands to is the key to playing nice with imperative constructs like break and continue.

Re:Rust and the Blub Paradox by steveklabnik on Saturday January 23, 2016 @02:42PM (#10959721)
The usual implementation of the Either/Option monads already does this though:

    instance Monad Maybe where  
        return x = Just x  
        Nothing >>= f = Nothing  
        Just x >>= f  = f x  
        fail _ = Nothing  
and

  instance (Error e) => Monad (Either e) where  
      return x = Right x   
      Right x >>= f = f x  
      Left err >>= f = Left err  
      fail msg = Left (strMsg msg) 
The end result is still a value of that type. You get the short-circuting behavior as soon as you hit Nothing/Left.
Re:Rust and the Blub Paradox by pcwalton on Saturday January 23, 2016 @02:53PM (#10959764)
It only short-circuits to the end of the do block. But once you leave the do block the error isn't propagated anymore.
Re:Rust and the Blub Paradox by steveklabnik on Saturday January 23, 2016 @03:12PM (#10959856)
Right. Maybe this is because I tend to write small functions, but the amount of things that end in `Ok(())` especially with IO still makes me think it would be useful.
Re:Rust and the Blub Paradox by pka on Saturday January 23, 2016 @02:51PM (#10959757)
Can't break be simulated by something like MaybeT? And forWithBreakM :: [a] -> (a -> m (Maybe b)) -> m [b] that stops when f yields Nothing? (isn't this actually sequence . forM?)
Re:Rust and the Blub Paradox by pcwalton on Saturday January 23, 2016 @02:59PM (#10959797)
Yeah, there are transformations that we could apply to the code to make it work. But those transformations aren't trivial in the general case: how about breaking out of multiple loops or returns out of the function from inside loops? At some point, the transformations that we'd have to do would get so complex they'd hinder the programmer's mental model of what code will get generated. We'd also have to do a fair bit of work to make sure the optimizer can figure out what we're encoding so as to not lose performance.
Re:Rust and the Blub Paradox by dbaupp on Saturday January 23, 2016 @06:40PM (#10960662)
I wrote a comment a while ago that has some code examples: https://github.com/rust-lang/rfcs/pull/243#issuecomment-8220... (and the following two comments)
Re:Rust and the Blub Paradox by tome on Saturday January 23, 2016 @01:00PM (#10959222)
> I have spent a lot of time studying error handling and even now have a sort of "theory of errors" that I will sometimes draw out for people on a blackboard

I would be very interested in a blog post on this.

Re:Rust and the Blub Paradox by steveklabnik on Saturday January 23, 2016 @01:26PM (#10959325)
Have you seen https://github.com/rust-lang/rfcs/pull/243 ? What do you think of it?
Re:Rust and the Blub Paradox by Rusky on Saturday January 23, 2016 @02:27PM (#10959652)
What do you see as unusable about Rust's error handling? It's heavily inspired by monadic exceptions.
Re:Rust and the Blub Paradox by Manishearth on Sunday January 24, 2016 @03:30AM (#10961945)
Rust errors _are_ monads. That style of error handling is known as "monadic error handling".

When the blog post says "you don't need to learn monads", it's being tongue-in-cheek. He's pointing out that whilst Rust errors are monadic, you don't need to learn monads to work with them.

To be fair to Haskell, it doesn't force you to learn what a monad is either (ha!), but often the full details of what a monad is are emphasized before teaching IO or error handling. Which works somewhat, but also gives monads their infamy.

Re:Rust and the Blub Paradox by eximius on Saturday January 23, 2016 @10:14PM (#10961301)
I think many of us would be interested in such a "Theory of Errors"