On Thu, Jul 31, 2025, at 15:32, Christian Schneider wrote: > Am 31.07.2025 um 09:10 schrieb Rob Landers <rob@bottled.codes>: > > I can see something like this being useful in niche applications. For > > example, I have a proxy generation class that creates something like this: > > > > public function remoteCall() { > > $this->operation = nameof($this->remoteCall(...)); > > $this->arguments = func_get_args(); > > throw new SpecialException(); > > } > > > > This SpecialException gets caught to let me know the application has > > consumed the one-use proxy. Using it looks something like > > > > rpc(fn(RemoteObject $o) => $o->remoteCall()); > > > > which just provides type-safe rpc at the expense of some boilerplate. > > > > I also use empty exceptions to "jump" the stack when my framework knows > > there is nothing more to do until outside events happen. I think I could > > probably use fibers to do the same, but if the user is using a fiber > > library; there is no guarantee they'll play nice together. This is true > > with exceptions as well, but the user has direct control over exceptions > > (do not catch Throwable, for instance). > > I'm not 100% sure I understood your examples but this smells like you are > using exceptions for flow (or maybe state?) control which I'm not sure I > would encourage. > > Regards, > - Chris >
It's explicitely to jump/unwind the stack -- PHP has no other way (other than suspending a fiber or yielding a generator) to jump/unwind the stack to a given point. Fibers are the superior way here, but even then, throwing from the fiber is still the best way to terminate it and force a GC of the stack there. This is basically using it as a longjmp (in C terms) which PHP doesn't have any other way to express. They're not used for flow control, or state. They merely force PHP to unwind the stack to a known place (all possible side-effects have already been done and it is either throw -- or wait for an external event, potentially forever -- which consumes memory and a thread). — Rob