News for hackers. Stuff that matters.
Re:Elegant Error Handling with the JavaScript “Either” Monad by jtdev on Wednesday June 19, 2019 @08:03AM (#20222513)
The arguments here against try/catch are superficial and in no way compelling enough for me to adopt this pattern for error handling. Seems to be a solution looking for a problem... stop trying to be so clever - focus on writing clean, readable, simple code.
Re:Elegant Error Handling with the JavaScript “Either” Monad by namelosw on Wednesday June 19, 2019 @08:30AM (#20222669)
I don't use this pattern to deal with the problems in my day to day JavaScript code in case other people confuse. I just think it's unfair to simply believe this is complex. It's simpler on mental. I'm not encouraging people to use this style, it's just some random defense.

This pattern is not more complex than try/catch. It's just JavaScript lack constructs to make the writing much less verbose. (we could abuse async/await but it's tricky).

Try/catch is an extra language construct which is confusing - it has dynamic semantics just like JavaScript's weird 'this' behavior. And it's leaky just like null - when you forgot to handle something, the whole thread explodes. Besides, it's not an expression, which means it's harder to refactor or return with function, passing as an argument, etc. On the contrary, Either would be just fine everywhere, just typical functions and values.

Another use case is when you want to collect the errors along the road, instead of failing fast behavior, in this case, Either would be easier than try/catch.

Re:Elegant Error Handling with the JavaScript “Either” Monad by dyeje on Wednesday June 19, 2019 @09:42AM (#20223243)
It may not be complex, but it's certainly obscure. Any JavaScript developer could understand the try/catch example but many would struggle with the Either example.
Re:Elegant Error Handling with the JavaScript “Either” Monad by lmm on Wednesday June 19, 2019 @08:11AM (#20222551)
> stop trying to be so clever - focus on writing clean, readable, simple code.

That's exactly what using either instead of try/catch does! try/catch are magic language keywords that create invisible, surprising control flow. Either is plain old code written in the normal language, with functions that follow the normal rules.

Re:Elegant Error Handling with the JavaScript “Either” Monad by jtdev on Wednesday June 19, 2019 @08:16AM (#20222571)
All language keywords are “magic” to some degree. The control flow that try/catch creates has never been surprising or invisible in my experience.
Re:Elegant Error Handling with the JavaScript “Either” Monad by cheeze on Wednesday June 19, 2019 @08:21AM (#20222604)
Fully agree. IMO this is the same argument as "the for loop is a magic keyword" which just isn't true.

Try/catch makes it _incredibly_ clear what you're trying to do. Kids who graduate college and get their first real job understand what a try/catch does. A random contributor to an OSS project knows what try/catch does.

Meanwhile, I'd be willing to bet that not even 10% of programmers could actually explain what a monad is.

I'm sure there is a place for this elegant error handling, but in most codebases it seems like a pretty big complexification for not all that much benefit. Sure, the code might even be "more correct" (whatever that means), but if Samantha the intern can't pick it up rather quickly, it probably isn't all that well suited for mainstream usage.

Re:Elegant Error Handling with the JavaScript “Either” Monad by lmm on Wednesday June 19, 2019 @08:44AM (#20222758)
> IMO this is the same argument as "the for loop is a magic keyword" which just isn't true.

The for loop is indeed a magic keyword, though it's less surprising/magic than try/catch; most of what for does could be done by a plain old function.

> Meanwhile, I'd be willing to bet that not even 10% of programmers could actually explain what a monad is.

Don't try to generalize prematurely. Considering Either on its own, it's simpler than try/catch and can replace their use cases. If you'd started with Either, try/catch would seem like the overcomplicated solution in search of a problem that it is.

Re:Elegant Error Handling with the JavaScript “Either” Monad by cheeze on Wednesday June 19, 2019 @08:55AM (#20222824)
> If you'd started with Either, try/catch would seem like the overcomplicated solution in search of a problem that it is.

But we didn't start with Either, which IMO is an incredibly important distinction.

Bolting things like this onto the language after the fact isn't the same as having first class support by default (like in say, Haskell)

Re:Elegant Error Handling with the JavaScript “Either” Monad by agentultra on Wednesday June 19, 2019 @09:39AM (#20223214)
Haskell doesn't have special support for Either. It's a plain old data structure with a few type classes. You can write Either in any language that supports passing functions as parameter values.

It's taking the logical disjunction operator, `||` in many languages, and sticking it in a data structure. You can now pass it around like a normal JS value and combine it with other such values.

The benefit of this over exceptions is that for unexceptional situations you don't end up throwing away the context of your computation if something takes the "bad path." Instead of jumping to the exception handler and losing all of your data your program can handle the situation at the site of the error where it has the most context to solve the issue.

TFA wasn't advocating abandoning try/catch -- it was suggesting that for non-exceptional cases it will make your code cleaner.

Re:Elegant Error Handling with the JavaScript “Either” Monad by IanCal on Wednesday June 19, 2019 @09:41AM (#20223232)
I think Maybe, Either, etc. are just implemented in regular Haskell, they're not special things in the language.
Re:Elegant Error Handling with the JavaScript “Either” Monad by true_religion on Wednesday June 19, 2019 @08:46AM (#20222777)
Almost all special purpose control syntax can be replaced by a series of function calls, but the value of syntax is clarity of intent.
Re:Elegant Error Handling with the JavaScript “Either” Monad by RHSeeger on Wednesday June 19, 2019 @09:43AM (#20223246)
> I'd be willing to bet that not even 10% of programmers could actually explain what a monad is.

To be fair, I don't think you need to really understand what monad is to understand Either.

Re:Elegant Error Handling with the JavaScript “Either” Monad by Fellshard on Wednesday June 19, 2019 @09:07AM (#20222919)
This argument doesn't hold with me, because while try-catch is very clear in what it does, the exception-/throwing/ mechanism is not. Try-catch is only useful insofar as you know exactly what you're trying to catch. Anything else is basically undefined behaviour; a jump straight to your catch block from anywhere in the application, as far as your intuition is concerned, a far cry from the controlled nature of loops.
Re:Elegant Error Handling with the JavaScript “Either” Monad by lmm on Wednesday June 19, 2019 @08:38AM (#20222722)
> All language keywords are “magic” to some degree.

Agreed. Every keyword adds complexity to the language; the fewer your language needs, the better. If your language has first-class functions and polymorphism (and any serious language does these days), there's no need for special-case control flow keywords; better to have a design like e.g. Smalltalk, where if/while/... are just normal functions.

> The control flow that try/catch creates has never been surprising or invisible in my experience.

One of the biggest production bugs I saw happened because of removing an unused variable (the function looked correct, but actually the unused variable right at the top of the function was throwing an exception; the fallback code path was correct, but the function itself was implemented wrong). It's the same problem as https://glyph.twistedmatrix.com/2014/02/unyielding.html - you can't tell which function calls might throw by looking at them, and most of them don't, but some of them do. And on top of that you have the goto-like "action at a distance": starting from a given catch there's no way to find the corresponding throw (or vice versa). You can't even tell when a catch is completely unused.

Re:Elegant Error Handling with the JavaScript “Either” Monad by Udik on Wednesday June 19, 2019 @09:02AM (#20222875)
> Every keyword adds complexity to the language

Easily refuted observing that you could strip languages of many of their keywords (for example replacing for and while with if and goto), and you'd end up with less readable code. Keywords are often added to make languages simpler, at least because they declare the intention of the developer.

Otherwise, Brainfuck would be the least complex language to write code in.

Re:Elegant Error Handling with the JavaScript “Either” Monad by lmm on Wednesday June 19, 2019 @09:35AM (#20223176)
You're conflating the complexity of the language itself with the complexity of code written in that language. Brainfuck is a famously simple language; brainfuck codebases are quite complex. Sometimes building complex functionality into a language might be worthwhile, if it allows you to simplify code written in that language. But since a developer working in the language has to be able to understand both the language and the codebase they're working on, you need to be careful about that tradeoff, only adding to the language those features that are general and powerful enough to simplify a lot of codebases. Otherwise you blow the whole complexity budget on language functionality, leaving the developer with no spare mental capacity to understand the specific codebase - even if their codebase makes no or minimal use of some of those complex language features.

Better, where possible, to implement general-purpose reusable functionality in libraries written in ordinary code in the language. That's a win-win approach: reusable library code can simplify codebases written in the language, but since it's plain old code that follows the normal rules of the language, a library doesn't add language complexity that the developer is forced to keep in mind.

Fundamentally, the key to making codebases in your language understandable is to be compositional: make sure that the developer can easily understand the combination of a and b if they understand a and b separately. Library functions do that, because you can understand how code that calls a library function behaves without needing to understand what the library function does. But language features like throw/catch don't do that: you need to understand what throw does if you are to understand code that calls a function that throws, even if the code you're trying to use doesn't throw itself.

Re:Elegant Error Handling with the JavaScript “Either” Monad by venuur on Wednesday June 19, 2019 @11:09AM (#20224043)
Sounds like you’d enjoy an R5RS scheme. Minimal syntax goes a long way. Unused variables throwing exceptions definitely seems like an over accumulation of technical debt.
Re:Elegant Error Handling with the JavaScript “Either” Monad by dropofwill on Wednesday June 19, 2019 @08:35AM (#20222701)
It depends on how it is used. I’ve definitely seen it used like a goto mechanism (on the JVM, i don’t write much JS), e.g. throw x in y to skip these business logic steps in z, and that makes my head hurt.

Personally I just try not to throw exceptions when compensation/recovery is expected. If something should be handled by the caller put it in the return type, if it’s really fatal give up and log a stack trace.

Re:Elegant Error Handling with the JavaScript “Either” Monad by Merad on Wednesday June 19, 2019 @01:20PM (#20225190)
I'm struggling to see how try/catch is either magic or surprising unless you simply aren't familiar with exception handling.
Re:Elegant Error Handling with the JavaScript “Either” Monad by wvenable on Wednesday June 19, 2019 @02:06PM (#20225576)
> try/catch are magic language keywords that create invisible, surprising control flow.

I'm surprised people believe this. If you added multiple returns to every function and manually propagated every error you'd get exactly the same thing as try/catch. It's existence comes from not wanting to do all this pointless boilerplate and instead having the compiler do it for you.

Re:Elegant Error Handling with the JavaScript “Either” Monad by lmm on Friday June 21, 2019 @01:19AM (#20240063)
> If you added multiple returns to every function and manually propagated every error you'd get exactly the same thing as try/catch.

You'd get the same control flow, but it would be visible in your code instead of invisible/magic.

> It's existence comes from not wanting to do all this pointless boilerplate and instead having the compiler do it for you.

Right, but making it be completely invisible goes too far - it's the same problem as AOP.

Either gives you the best of both worlds - minimal boilerplate, but you can still see what's going on.

Re:Elegant Error Handling with the JavaScript “Either” Monad by MapleWalnut on Wednesday June 19, 2019 @08:15AM (#20222567)
Maybe in plain JS, but with Typescript this Either pattern will force you to handle errors unlike untyped try, catch.
Re:Elegant Error Handling with the JavaScript “Either” Monad by cousin_it on Wednesday June 19, 2019 @08:08AM (#20222534)
Agreed. I never understood the love for Either-based error handling in Haskell and other languages. It's such a bare bones system. If you add all the features that people want from an error handling system, like stack traces; and remove the misfeatures that nobody wants, like Either<IOError,Either<MathError,Result>> being a pointlessly different type from Either<MathError,Either<IOError,Result>>; you end up with (surprise!) try-catch.
Re:Elegant Error Handling with the JavaScript “Either” Monad by roblabla on Wednesday June 19, 2019 @08:37AM (#20222716)
I'm not familiar with Haskell, but Rust's `Result` type is the same idea, and I wouldn't want to trade it for try-catch. It supports backtraces[0], has a simple way to turn errors into a "catch-all" type[1], but it is significantly less complex since it reuses the basic return value mechanism a function has.

If you want to exit the program because the error can't be handled (similar to an unhandled exception), rust has a different concept for it, panics, and any Result can be turned into a panic via `unwrap()`.

IMO both are important: panics represent unrecoverable errors, while Results can be acted upon (for instance, if read() returns Err(EINTR), you'll want to retry the read)

[0]: Granted, you need to write some boilerplate to get the backtrace on error creation.

[1]: You can cast all errors to `Box<dyn Error>`, a heap-allocated dynamically dispatched Error type.

Re:Elegant Error Handling with the JavaScript “Either” Monad by kmonsen on Wednesday June 19, 2019 @08:54AM (#20222820)
So in rust you write with result and in js you use try/catch. Pretty simple, and readers will understand the code.
Re:Elegant Error Handling with the JavaScript “Either” Monad by roblabla on Wednesday June 19, 2019 @10:33AM (#20223696)
Oh I agree, and definitely don't recommend using Result in JS, the language is just not tailored for it. I was specifically addressing

> I never understood the love for Either-based error handling in Haskell and other languages.

Re:Elegant Error Handling with the JavaScript “Either” Monad by lmm on Wednesday June 19, 2019 @08:49AM (#20222791)
> If you add all the features that people want from an error handling system, like stack traces; and remove the misfeatures that nobody wants, like Either<IOError,Either<MathError,Result>> being a pointlessly different type from Either<MathError,Either<IOError,Result>>; you end up with (surprise!) try-catch.

What does a function that doesn't error look like under try-catch? How do you tell it apart from a function that can error.

It's the same argument as null/Optional. Yes, Optional behaves the same as a nullable value; the point is that languages with Optional allow you to have values that aren't nullable.

Re:Elegant Error Handling with the JavaScript “Either” Monad by cousin_it on Wednesday June 19, 2019 @09:42AM (#20223240)
> What does a function that doesn't error look like under try-catch? How do you tell it apart from a function that can error.

By the empty throws clause.

Re:Elegant Error Handling with the JavaScript “Either” Monad by lmm on Wednesday June 19, 2019 @09:57AM (#20223373)
Edit: Parent was edited, previously suggested "Java-style exception specifications". As far as I know every language with "throws clause"s has the kind of problems I describe below though.

Three major problems: they interact inconsistently with generics, you can no longer take a function's result and store it as a value, and you still can't tell whether a function might throw by looking at the point where it's called.

A good version of exception specifications would be lightweight syntax sugar over either (in the same way that a good version of async/await is a lightweight syntax sugar over futures/promises). But I'm not aware of any language implementing that; I guess once you have working Either there's not enough value in providing an alternative syntax for it.

Re:Elegant Error Handling with the JavaScript “Either” Monad by cousin_it on Wednesday June 19, 2019 @11:19AM (#20224122)
Actually I thought a bit and realized that I don't want to defend checked exceptions. Let me amend the previous answer to "I prefer such functions to be interchangeable".
Re:Elegant Error Handling with the JavaScript “Either” Monad by lmm on Wednesday June 19, 2019 @11:38AM (#20224288)
If those functions are interchangeable then you potentially have to deal with exception control flow on every line, or even within a single line. It makes it very hard to reason about all possible paths through a given function and do things like safe resource management (e.g. you always have to handle the possibility of further exceptions in your exception-handling code path).

For system failures it's ok because the only handling you're going to do is retry at high level (and so even languages with an Either-oriented style tend to have some form of "panics" or exceptions for that kind of failure). But it can be a real problem when that also happens for "normal failure" paths like bad user input where you want to actually have business logic that handles and perhaps recovers from the failure.

Re:Elegant Error Handling with the JavaScript “Either” Monad by cousin_it on Wednesday June 19, 2019 @02:20PM (#20225734)
I think you can often avoid reasoning about all possible paths, by having one try-finally block per each resource to be freed.
Re:Elegant Error Handling with the JavaScript “Either” Monad by 0815test on Wednesday June 19, 2019 @09:09AM (#20222934)
The types are definitely isomorphic, but the difference between them is not "pointless". You could have Either<IOError, Either<IOError, Result>> and want to preserve the information about which step led to an IOError outcome.
Re:Elegant Error Handling with the JavaScript “Either” Monad by cousin_it on Wednesday June 19, 2019 @09:58AM (#20223382)
That information shouldn't be in the type, because it makes functions pointlessly non-interchangeable. With try-catch, a superset of that information is preserved in the stack trace, and functions stay interchangeable.
Re:Elegant Error Handling with the JavaScript “Either” Monad by esarbe on Wednesday June 19, 2019 @12:49PM (#20224925)
I consider the error types to be a useful information that should absolutely be part of the method type.

If a method can fail on IO that's different than if it cannot fail. And the surrounding code has to account for that.

So, you might think that the methods are interchangeable if the error type is not present in the signature but this is actually wrong. Different failures have to be handled differently.

(I assume that you are /not/ talking about valid error cases in the problem domain that also might have to be handled)

Re:Elegant Error Handling with the JavaScript “Either” Monad by chii on Wednesday June 19, 2019 @09:01AM (#20222857)
why is either wrapped in eithers in your example? That feels like wrong code to me. Wouldn't it be Either<(MathError|IOError), Result>, and you pattern match the error or result?
Re:Elegant Error Handling with the JavaScript “Either” Monad by ahallock on Wednesday June 19, 2019 @09:52AM (#20223328)
Saying something is superficial and too clever is not a counter argument, but rather a reaction, I think, to it being radically different from what you're used to. I'm not saying it's necessarily better, but maybe approach things with an open mind.