On Thu, Aug 11, 2022 at 11:06:45PM +0000, Adam D Ruppe via Digitalmars-d-learn wrote: > You might find my recent blog post interesting too: > > http://dpldocs.info/this-week-in-d/Blog.Posted_2022_08_01.html#exception-template-concept > > and a draft of some more concepts: > http://arsd-official.dpldocs.info/source/arsd.exception.d.html > > > I also find the lack of information disturbing, but I also hate > formatting it all into strings, so I wanted to experiment with other > options there that avoid the strings.
I think the OP's idea is somewhat different: adding contextual information to a propagating exception that the throwing code may not have access to. I've often encountered this situation: for example, I have a program that's driven by script, and contains a bunch of code that does different computations which are ultimately called by the script parser. There may be an error deep inside a computation, e.g., a vector was zero where it shouldn't be, for example, and this may be nested inside some deep expression tree walker. So it throws an exception. But the resulting message is unhelpful: it merely says some obscure vector is unexpectedly zero, but not where the error occurred, because the expression walk code doesn't know where in the script it is. And it *shouldn't* know -- the filename/line of a script is completely orthogonal to evaluating expressions; for all it knows, it could be invoked from somewhere else *not* from the input script, in which case it would be meaningless to try to associate a filename/line with the exception. Expression evaluation code should be decoupled from parser code; it shouldn't need to know about things only the parser knows. And besides, if the expression code wasn't invoked from the parser, the exception shouldn't include filename/line information where there isn't any. It should be the parser that tacks on this information when the exception propagates up the call stack from the lower-level code. In fact, the exception should acquire *different* contextual information on its way up the call stack, depending on what triggered the upper-level call. If the expression evaluation was invoked, say, by network code, then the exception when it arrives at the catch block ought to carry network source IP information, for example. If it was invoked by simulation code, then it should carry information about the current state of the simulation. In the other direction, if the expression evaluator code calls, say, std.conv.to at some point, and .to throws a conversion error, then the outgoing exception should carry some information about where in the exception the problem happened. There is no way std.conv could know about this information (and it shouldn't know anyway); the expression code should be the one tacking this information on. And as the exception propagates upwards, it should gather more higher-level contextual information, each coming from its respective level of abstraction. The OP's idea of wrapping throwing code with a function that tacks on extra information is a good idea. Perhaps the use of strings isn't ideal, but in principle I like his idea of exceptions acquiring higher-level information as it propagates up the call stack. T -- PNP = Plug 'N' Pray