3 ms·
> Throw an error and move on with your life No, absolutely not! Panics are the result of conditions that absolutely should crash the program! They are not err
by usrbinbash 3y ago
> Throw an error and move on with your life
No, absolutely not!
Panics are the result of conditions that absolutely should crash the program! They are not errors, they are not similar to exceptions, they are conditions that should not occur, and thus if they do occur, either the program itself, or the platform it is running on, has a problem that needs to be solved before the program runs again.
If a cars fuel is running low, it should turn on a warning light and inform the driver that he should find a gas station. If a piece of the road is suddenly missing, the car needs to stop.
If a panic occurs, I don't WANT the program to continue executing! That would lead me right back into C land, where an out-of-bounds memory access would silently start to poison my program and crash it days after the actual error ocurred, if i'm lucky! If I'm unlucky, and the process needs to be sufficiently privileged, it would kill the server, again several days (or weeks) later, with slim-to-no chance for me to figure out what even went wrong.
- zoky 3y agoAnd why exactly do you trust a called method to determine whether or not you should be able to keep running? Like… do your job, you object. I didn’t load your library and call a method on you to tell me what the state of my system is, I just want you to either do what I asked you to do or fail gracefully, and then I can decide whether we crash or not. > If a piece of the road is suddenly missing, the car needs to stop. Uh, no. If a piece of the road is missing, it’s up to the driver to stop, not the car. The car has no business whatsoever determining whether the road exists or not, except inasmuch as it communicates to the driver “hey, whatever the heck this is is difficult or impossible to drive on, your call what we do though.”
- zozbot234 3y ago> I just want you to either do what I asked you to do or fail gracefully, and then I can decide whether we crash or not. Then you're looking for resumable conditions, which just so happen to be effectively isomorphic to async-await. (The called function is effectively a piece of async code which 'awaits' upon a failure condition, after which it can either be resumed or canceled as with an ordinary panic.)
- usrbinbash 3y ago> just want you to either do what I asked you to do or fail gracefully And most of the time, this is EXACTLY what happens. In fact most libraries that do use panics, recover them internally and return errors to the callers. Again: panics are not errors, panics are not exceptions. A library should never panic in a way that it's caller notices, UNLESS it met a condition that simply is not recoverable, not by the library itself, and not by it's caller. Yes, this requires care by the libraries authors not to overuse panics. Yes, there are libraries that do overuse them. No, this doesn't change anything about what I wrote. If a library I use would do that, I would either fix the library, or find a better one. > Uh, no. If a piece of the road is missing Okay, let me try again with a better analogy: If a cars engine breaks down, the car will stop. It doesn't matter if the driver wants the car to go for another 100 kilometers. It stops. Period. Not because anyone or anything "wants" the car to stop, but because its engine "package" met a condition, under which the further running of whatever context it is used in (in this case, the car), is no longer feasible and/or possible. That is exactly what panicking in a way that hits the runtime communicates: Oh noes, the engine just broke down, and now the machine can no longer run.
- zoky 3y agoI’m not sure how valuable these analogies actually are, but your example of the broken engine really seems to go towards my point. If the car breaks down, the driver still has several options: coast downhill, switch to a different car, pull a bicycle out of the trunk, or just get out and continue on foot. But the car enforcing the end of the trip by simply exploding and killing the driver isn’t really an acceptable response to engine failure. A library that unrecoverably crashes your program for any reason is defective by design, and a programming language that purposely allows a library to do so as a design choice is also defective by design in my opinion.
- usrbinbash 3y ago> If the car breaks down, the driver still has several options: The one option he doesn't have though: Continue running the car as-is. And that's the point I am making. > and a programming language that purposely allows a library to do so as a design choice is also defective by design in my opinion. You are entitled to your opinion of course, but I'm not going to agree, and it seems a lot of people are completely fine with that design decision: https://madnight.github.io/githut/#/pull_requests/2023/3 https://madnight.github.io/githut/#/pull_requests/2023/3 Again, the library isn't "crashing the program". The library meets a condition under which it can no longer function, no matter what the caller does, and can no longer function in a way that makes running the entire program infeasible. That is the point of panicking and not recovering it within the library. And yes that is the libraries call to make. Yes, it needs to have a very good reason to make that call. Very few libraries panic in that way. And the ones that do, and are widely used, have very good reasons to. If libraries do so without a good reason, then people stop using them.
- iainmerrick 3y agoWhy would there be a "recover" function, then? A quick google turns up https://go.dev/blog/defer-panic-and-recover https://go.dev/blog/defer-panic-and-recover, which says: For a real-world example of panic and recover, see the json package from the Go standard library. It encodes an interface with a set of recursive functions. If an error occurs when traversing the value, panic is called to unwind the stack to the top-level function call, which recovers from the panic and returns an appropriate error value That's panic and recover used for control flow, just like might use exceptions in other languages. Looks like panic has at least two purposes, depending on whether you recover or not?
- usrbinbash 3y ago> A quick google turns up https://go.dev/blog/defer-panic-and-recover https://go.dev/blog/defer-panic-and-recover, which says: And another quick googling turns up this: https://github.com/golang/go/issues/26799 https://github.com/golang/go/issues/26799 which says: However, this is a poor example and a misuse of panic and recover as exceptions. See https://golang.org/doc/effective_go.html#panic The example will be invalid soon with the release of go 1.11 as well. The panic/recover was removed from the unmarshal code. See master's So no, panic and recover are not meant to be used as control flow. Yes, they CAN be used that way. I also CAN use pythons `eval` a lot, use a scripting language as my command line interpreter, or make an apple-pie with onions and garlic. As for why `recover` exists in the first place: Packages should have the ability to stop internal panics. There are various reasons for that, some worse than other. For example it is probably okay if a package doing sensor readouts recovers from a division by zero and replaces it with an error saying that the sensor value makes no sense.
- iainmerrick 3y agoAha, good find, thanks! Maybe they need to work on their SEO. :)