I feel like the author is only thinking about high-quality production code. Often you're just writing a 30-line snippet of throwaway code to test something out. And then unwrap() is a bit nicer than expect("").
My thoughts exactly. Without panic people (myself included) would just write expect("") when we want the behavior of unwrap().
I have some Rust code that I'm the only user of; in those cases I'd rather investigate an error when it comes up than spend time upfront thinking about errors that may never happen.
For me, the problem isn't `unwrap` vs. `expect`, it's that I can't statically guarantee that particularly mission-critical code never panics.
I can be as careful as I want in writing panic-safe code, but there's no ergonomic and non-hacky way to ensure that I don't use third-party crates in a way that can possibly panic either.
> I can be as careful as I want in writing panic-safe code, but there's no ergonomic and non-hacky way to ensure that I don't use third-party crates in a way that can possibly panic either.
There's also no way to ensure those third-party crates don't enter an infinite loop; at some point, if you need to guarantee your program doesn't diverge, you need to either trust the libraries you're using to behave reasonably, or you need to audit them yourself. Removing `unwrap` wouldn't solve that problem, and given how easy it is to lint for, it doesn't even meaningfully contribute to its difficulty. As the GP and some of the other top level comments point out, `unwrap` is a genuinely useful tool to have in the std lib, so advocating for its removal (or that it was a bad choice to begin with, presumably hoping that future languages will avoid including amenities such as `unwrap`) seems like a poor design trade-off from where I stand.
I am in no way agreeing with the idea that `unwrap` should be removed. I simply wish it were possible to assert statically at compile time that my application will not panic.
Being unable to also detect infinite loops does not diminish this utility. I simply wish to reduce the likelihood that my mission-critical programs diverge as much as is possible. Being perfect is not a requirement.
Being able to statically assert your program does not panic is predicated on being able to detect infinite loops. For example a panic could be detected to occur after a loop which may or may not be infinite. If you can't detect infinite loops you also can't detect if the program will panic or not.
Why the insistence that this has to be perfect for it to be of any use?
If the optimizer can prove it isn’t used and elides any code that might call it, great. If it can’t, I can rewrite my code to not use that function or call it in a way where the optimizer can make that guarantee.
There are all sorts of useful things that technically depend on deciding the halting problem, but turn out to be pretty easily solvable for virtually all practical cases.
What exactly is gradual about the question: "Can this program panic?". Either you are optimistic and allow any unproveable panics through and now you program will panic in practice. Or you are pessimistic and basically disallow any practical program.
There are a lot of cases where a gradual approach works well. But something so fundamental and important like "Can this program panic?" is not one of those cases.
I was addressing your odd fixation on not being able to prevent an infinite loop. That's not a real downside. We can still make progress in many other areas in the meantime.
It's not about about being able to prevent an infinite loop. It's about being able to say this program really doesn't panic. Which is a very important property. For example the Linux Kernel requires Rust code to not panic. There was a lot of work done to ensure this was at all possible. And it wasn't to try and statically assert whether a piece of code panics. It was just disallow panics outright. Do you think these compiler developers just took that route because it's fun? Or because they are "oddly fixated on the halting problem"?
I don't know why you are so combative and immediately used the opportunity to reframe what I said above into attacking a good reasonable problem that we would all like eliminated (the halting problem) but I'll ask you to stop because that's not discussing in good faith; you seem to be on the lookout to attack someone and I am seriously not interested in that.
--
Having said that: being able to disable / remove `.unwrap` and co. with a compiler flag -- as you seem to imply is the case in the Linux kernel branch of Rust -- would prove hugely beneficial to no small amount of library and app developers.
And guaranteeing no panics isn't that hard. Sure the POSIX standard and Linux in particular are vague in many places but I think it's fairly reasonable to be able to guarantee that a program that doesn't use filesystem or network can never panic just through dependency analysis (e.g. no API is used that can propagate a panic from the kernel).
How useful would that program be is another discussion entirely though (quite an amusing one at that).
My point was and remains that not being able to detect infinite loops is not indicative of the ability to prove that panics [due to system / kernel API carrying them over to you or just straight up blowing up your program] will not occur. And you seem to claim the opposite?
I'm mostly writing "high quality production code" - and for logic errors which can't be gracefully handled I find little to no difference between .unwrap() and .expect(). What I'm usually mostly concerned about is understanding where the error happens if the application crashes, and a stack trace is the best way to obtain this information - not the actual text message. From a crash report and a stack trace it's usually clear what happened, and I think using either a custom panic! call or except would only be helpful if more information about the current state of the program would be helpful to debug the issue (like "expected value to be between 127 and 255, but not 1234").
For errors that can be gracefully handled - sure, using ? is definitely preferred to any kind of panicking.
It's as if people don't read the article before commenting, because the author mentions exactly this use case too:
> Perhaps you’re doing prototyping and just need something that works most of the time, or you’re writing a simple app with limited error-handling needs. Some people use unwrap and expect for this situation, but I don’t. I use ? even in that situation, because I never know when prototype code might have to escalate to production code – either so suddenly there’s no time for me to intervene and improve the error handling or so gradually there’s no occasion for it and it never gets prioritized. Fixing crappy usage of ? in such a situation is way easier and more likely to happen than fixing a bunch of expects or unwraps.