On Sat, Apr 26, 2025, at 11:19 AM, Rob Landers wrote: > Hey Larry, > > I’m still digesting this, but I wonder if this problem (errors vs > non-world-ending errors vs happy path) is a problem due to people often > making warnings into exceptions? > > I feel like many devs/frameworks “abuse” (for lack of a better word) > the error handling system to make everything into a world-ending-error > when it is not.
Yes, it's common for devs today to use exceptions in inappropriate ways. I've done it myself at times. The problem is that we don't have a tool fit-for-purpose for "your input is invalid in a totally predictable way." So you can either squeeze an error code into the return value (null or otherwise), which sucks, or abuse exceptions, which sucks. That's exactly the issue I want to solve, by offering a tool more purpose built for that case. > Even over the last few versions of PHP, more and more warnings have > turned into exceptions that maybe ought not be. > > Overall, this has resulted in a somewhat more inconsistent language > than it was previously. For example, you used to be able to consider an > array as a field of infinite nulls. You could iterate over an infinite > set of keys and get nothing but null. This made it easier to explain to > junior devs at the time. Now, you have to explain it as a > hash-map-but-sometimes-array-thing that emits warnings when a key > doesn’t exist but will still give you null. > > We are currently in this weird place between “infinite field of nulls” > and “sparse array/hash-map” but not quite either one — depending on > what you do with that warning. Treating arrays as an infinite series of nulls, however... no, that's always been a developer error. If that was the mental model you were working from, it's an incorrect mental model, and it always has been, since forever. Arguably it's PHP's fault for letting you develop that broken mental model because it didn't complain loudly; both PHP and MySQL started life with lots of "we'll quietly assume what you probably meant and not tell you that you're wrong" features, and both have had a very long, very painful process of correcting that fundamental mistake. Anyone working from an "infinite series of nulls" model has been an unfortunate victim of that design flaw. It's possible we could use light-checked exceptions as a better way of signaling "hey, you're reading an invalid key". So far I've only considered them as a function-boundary thing, but we could probably look into raising them implicitly for certain read operations. (Maybe only on objects that are using Gina's forthcoming Fetch interfaces? I dunno.) > It would be great if we could pick one and I think it would also solve > the whole “is null an error or a value” problem. Just having an "alternate null" is not viable for many reasons, which I go into in the article I linked before so I won't repeat it here. > I personally wouldn’t like checked exceptions. I have PTSD from Java’s, > so just hearing that phrase gives me flashbacks of catching dozens of > potential exceptions. In Go, yes there is some boilerplate, but it’s > not that bad and it easy to deal with, especially with IDE support. As the Midori article I linked explains, the PTSD you have from Java exceptions is not an issue with checked exceptions; it's an issue with Java's terribly designed exception system, combined with all values being inherently nullable. A well-designed checked exception system doesn't "force you to handle all these error cases". A well-designed system "tells you every error case that you need to think about, and helps you deal with it." Smart usage of interfaces on the error values can make dealing with a whole class of issues easier, and some more ergonomic syntax than try-catch (such as Rust's ?) can make it less cumbersome. In a sense, checked exceptions show you exactly what you need to do in order to turn a partial function (that just dies on certain values in its input range) into a total function with two return channels (because you'll always get back a legit value, just sometimes the legit value is on the error pathway.) That both surfaces the unhappy paths (that any robust code should handle) and simplifies handling them. > As for a Result type, that’s already possible in user-land; what does > bringing it to the engine get us? Is it just a lightweight exception > without a trace to prevent the cost of generation? Why not just have a > pool of exceptions that you can just modify the message? A general purpose Result type requires generics, or else you lose all type info on what the real return value's type is. We don't have generics, so that's simply not an option. The separate channel approach gives us all the benefits of a Result type without the need for generics, and it's standardized in the language. A general purpose Result type is also very clumsy to use in practice, unless you have syntax optimized for working with it. Rust has its match statement (which supports pattern matching, decomposition, and multi-line statements specifically for dissecting a Result type) and ? operator, which is a one-character way to "pass on" the error to the caller, as though it were an unchecked exception. For PHP, we'd probably want a different set of syntax tools as our working model is different than Rust's. What those would be, I don't know yet. Hence this thread. --Larry Garfield