5 ms·
To be honest I don't think there's any practical difference between this and using `errno` in C. In fact, I suspect Go may have adopted a more complicated solut
by repsilat 14y ago
To be honest I don't think there's any practical difference between this and using `errno` in C. In fact, I suspect Go may have adopted a more complicated solution simply because we're squeamish about using global variables.
At the end of the day this solution doesn't work for "high level" code for the same reason `errno` and return codes aren't adequate - is forces the user to litter their code with explicit checks for exceptional cases. The whole point of exceptions is that they let the user write the code as if everything is peachy, to let the code bail out wherever appropriate, and to pass the buck for fixing it to someone who cares.
(I don't know anything about `panic`/`recover`.)
- chawco 14y agoThis was my assessment as well -- it's just a cleaner way to use errno. I do think a language got this system right -- conditions and restarts in Common Lisp solve this problem very well. I'm a bit perplexed that I haven't seen this model adopted a bit more widely in the programming world, particularly given how much of a headache exception semantics are.
- repsilat 14y agoHah, I have a bookmark on the CL approach I've been meaning to get to for months now. I guess I'll have to give it another whirl. Ack, and your sibling comment is pointing me to a monadic approach... I'm sure "learn about monads" is also languishing on my to-do list somewhere.
- motter 14y agoDo you have a link to the CL approach? Edit: A quick search turn up this interesting LtU discussion: http://lambda-the-ultimate.org/node/1544 http://lambda-the-ultimate.org/node/1544
- repsilat 14y agoI'm on a different computer now, but iirc the one I have bookmarked is http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html http://www.gigamonkeys.com/book/beyond-exception-handling-co... Thanks for your link too.
- gregschlom 14y agoVery interesting article, thanks for sharing. I just submitted it here: http://news.ycombinator.com/item?id=4521675 http://news.ycombinator.com/item?id=4521675
- chawco 14y agoThis entire book is a really good into to CL.
- saurik 14y agoThere was a great thread in a previous discussion on HN about error handling that had a reply from lkrubner (currently, and likely forever, the top response on that thread) that went into some detail, causing more ensuing discussion. (edit: Ah, and then he links to that same article you linked to!) http://news.ycombinator.com/item?id=4468849 http://news.ycombinator.com/item?id=4468849
- scott_s 14y agoIn "The Design & Evolution of C++" (http://www.stroustrup.com/dne.html http://www.stroustrup.com/dne.html), Stroustrup talks about termination versus resumption semantics for exceptions. Resumption was considered for C++, but rejected based on experience in the Cedar/Mesa system. There's a quote from that part of the book on Wikipedia: http://en.wikipedia.org/wiki/Exception_handling#Exception_handling_in_software http://en.wikipedia.org/wiki/Exception_handling#Exception_ha... Note that I'm not arguing that termination semantics are better - I've never programmed with resumption semantics, so I can't say. But that's why it's not in C++.
- chawco 14y agoThat's pretty shocking, given Stroustrup's propensity to just dump everything into C++. It's also a bit of a shame it didn't get a chance to see the wider audience C++ would've brought.
- scott_s 14y agoPeople have that impression - that Stroustrup "dumped everything into C++" - but it's demonstrably not true if you read D&E. Every new feature that made it into the language after the standardization point had a working implementation, and people had experience with that implementation. He goes over lots of rejected features. Also consider what your statement implies: Stroustrup put too many features into C++ (bad), but he did not put feature X into C++ (also bad). You're faulting him for accepting too much, but at the same time, for not accepting one in particular. Although it should really be noted that post-standardization, what made it into C++ was a committee decision, not Stroustrup alone.
- ynniv 14y agoBecause resumption wasn't actually necessary for such a context inquiry, they removed it and found a significant speed increase in that part of the system. s/resumption/exceptions/ and you have a secret to performance in Java. If this is the core reason for termination-only exceptions in C++, Stroustrup made a huge mistake: he presumed that the best exception handling for mature, stable code was the best exception handing for all code. But then he also threw in a lot of features that cripple the language from ever being able to create truly mature, stable code (see http://www.250bpm.com/blog:4 http://www.250bpm.com/blog:4). Now the most stable, mature libraries are written in C. C++ exceptions are then unreachable code, and a properly optimized programmer will never use them.
- eru 14y agoDo you have any opinion on using Monads for exception handling (like in Haskell)?
- Lambdanaut 14y agoI like them. The only annoyance is that you're forced to wrap your return value in a monad even if the function succeeds. That's type safety for you!
- eru 14y agoYes. But that's because the default is non-monadic wrapped and an assumption that it can't go wrong. I'd had to see non-monadic wrapped values to silentry go wrong or raise an exception. (You can do something like Go's panic in pure values. But you are not supposed to do that for recoverable conditions.)
- Evbn 14y agoIn practice, wrapping a return value in a monad looks exactly like returning a regular value in another language: return x.
- dllthomas 14y agoIt's a way of getting context-specific (but not error-specific) behavior, and when dealing with functions producing a polymorphic monadic value it threads very nicely. That said, the approach in Haskell of fail always taking a string (which doesn't necessarily get stored/used anywhere) has a bit less to recommend it. It's also slightly confused conceptually to put "fail" in the Monad typeclass but that mostly bugs the theorists. The biggest downside, though, is that it can often make the source of errors harder to find - cf. hunting NaNs in floating point arithmetic.
- eru 14y agoOh, we just pretend that the monad typeclass does not have "fail" in it. It's only useful for pattern match failures when using the do-syntax. I was talking more about the (Either Error) monad, which has not much to do with "fail". (Edited first sentence.)
- dsymonds 14y agoThe big problem with errno is that it's a global: there's exactly one of them for your program. As soon as you start using threads you are screwed. Go aims to make concurrency right. That means you can depend on a global variable for propagating error information. errno in C is ultimately because C doesn't have multiple return values, and the alternatives (pointer arguments as implicit output) are sucky. Go has multiple return values, and so returning an error is natural.
- fafner 14y agoerrno is thread locale in most modern implementations
- Erwin 14y agoerrno is generally defined to be a macro like: (errno_location()), at least when you use the -pthread option with gcc. The odd constructoin (the function returning an int which is dereferenced) allows the errno macro to work as an "lvalue", i.e. that you can still say "errno = 0" to clear its value.
- Jabbles 14y agoThe practical difference is that there is (partial) enforced checking of errors. If you do not wish to check the error code, you must be explicit. f := os.Create("output.txt") Will give a compile error multiple-value os.Create() in single-value context: and should be written as one of these: f, err := os.Create("output.txt") f, _ := os.Create("output.txt") where the second indicates that you are ignoring the returned error. I say "partial" because if you ignore all the return values you can implicitly ignore an error: fmt.Println("Hello") It is quite common to see: if err != nil { //handle error } in Go, as their philosophy is that the caller should handle the error, not an unrelated piece of code. Yes, this does sometimes look like "litter", and it doesn't really make for the most impressive code. However, you won't be surprised by it, it's simple to understand, and if something goes wrong, you'll know what, when, and what was done about it. This has been Google's opinion on C++ for a while. http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml?showone=Exceptions#Exceptions http://google-styleguide.googlecode.com/svn/trunk/cppguide.x... lists some pros and cons. Writing code that ignores errors is one way of writing code, I think it's idiomatic Java and Python (please correct me), but that's not the way that was chosen for Go. I don't really use panic() except to indicate bugs: if playerCount == 2{ go multiPlayer() } else if playerCount == 1{ go singlePlayer() } else { panic(playerCount) } However they can be useful inside libraries. For example if you call fmt.Printf("%s",s), where s has a method s.String(), will print the result of s.String(). Sound good? But what if s is a nil pointer? Well, you may wish s.String() to handle that and return "A nil s", which is fair enough. However is s.String does not handle this case it may panic(), leaving fmt.Printf to recover() and write "<nil>" instead. http://golang.org/src/pkg/fmt/print.go#L630 http://golang.org/src/pkg/fmt/print.go#L630
- kstenerud 14y agoThis doesn't sit well with me. Who is to say what's catastrophic and what's not? Should I use all libraries in fear because passing a nil pointer or an improperly formatted date may cause it to terminate the program with no recourse? Suddenly every library is a ticking time bomb with a scorched Earth policy for things it doesn't like. How am I to know what's going to cause my valuable program to simply die in the middle of the night? Look at the outdated/incomplete documentation? Pore over the complex code (if it's even available)? Now not only do I need to litter error value checks everywhere, but I also need to preemptively sanitize all input to any library calls I make and pray that I haven't missed something. This is simply trading one problem for another.
- toddh 14y agoSince errno is now thread local it's not the big deal it used to be, but it still contains no data, so returning objects is superior because it can provide error context and the error information can be chained together as flows up the stack. I was horrified at go's error handling policy until I learned multiple values could be returned from functions, that gets rid of the main problem with using error returns in C.
- deleted 14y ago[deleted]