On Tue, Oct 13, 2020 at 02:08:11PM -0000, jmwar...@gmail.com wrote:

> I am not particularly concerned with performance here. I am more 
> worried about code clarity, boilerplate that de-incentivizes a feature 
> and hidden values.

Okay.

> The current exception mechanism encourages passing, 
> effectively, un-named lists of parameters or building boilerplate to 
> create the equivalent of named tuples (e.args[0] or building an 
> __init__ that defines members).

I don't agree that it *encourages* that, more that it allows it.

I'd like to see the typical use you make of exceptions. For me, almost 
without exception (pun intended) the exception is intended for three 
purposes:

1. A human-readable error message:

    # expecting a prime number, but didn't receive one
    raise ValueError('argument is not a prime number')


2. A low-resolution mechanism for re-trying or suppressing errors:

    for number in numbers:
        try:
            process(number)  # May raise ValueError
        except ValueError:
            print("skipping non-prime")


3. A simple protocol for returning an out-of-bounds state flag, in the 
way StopIteration is used.

(Number 3 is technically a form of flow-control, but in practice the way 
it is used is quite simple.)

For those three purposes, I think exceptions are fine. But you seem to 
be using exceptions as some sort of dispatch mechanism.


> If the only value is the name, why not 
> just define it where you use it instead of creating an intermediary 
> class definition?


> I use string literals for state names all the time 
> instead of creating objects and importing them all over my code 
> because most of the time the mental overhead of imports and the like 
> isn't worth the ease and clarity of just passing a string.

I don't see that this situation is relevant. Your exception handling 
code seems to make use of a lot of internal state: you store variables 
as exception attributes, then extract them later. While I guess you 
could do that with strings:

    string = f'{spam}; {eggs}; {cheese}; {aardvark}'
    # later on...
    spam, eggs, cheese, aardvar = string.split(';') 

I'm guessing you don't. But that's what you're doing with the 
exceptions: you store a bunch of values into the exception object, then 
raise the exception, only to *immediately* catch it again, retrieve 
those same values, and use them. Why not just use the values directly?

(Based on your earlier pseudo-code example. Perhaps real code is 
different.)


[...]
> I mentally do think of this as just a convoluted function call 
> passing control.

I try to avoid convoluted code of any description. Sometimes I fail, but 
I don't do it intentionally.


> When you make that mentality switch then the current 
> mechanism starts looking either obfuscated or bloated for the reasons 
> I said above (passing anonymous lists of parameters, e.args, or adding 
> extra code and defining an object just to pass named parameters).

Doesn't that suggest to you that maybe you are using the wrong tool for 
the job, or using it badly? If serving soup with a carving knife 
requires you to create an obfuscated, bloated, convoluted framework, 
perhaps you would be better off using a ladle like everyone else :-)

I do look forward to seeing a more realistic example of what you are 
doing, because from the pseudo-code you supplied earlier, it looks like 
an obfuscated, bloated, convoluted way of doing something that is simple 
if you just don't use exceptions.


> I guess what I am _really_ suggesting here is more of a named return 
> that passes to the first block capable of handling it. That's really 
> what exceptions are conceptually doing, just make it more explicit.

Hmmm, are you thinking of message-passing mechanisms?

Your description sounds like Hypertalk and other XTalk programming 
languages, such as Apple's Hypercard in the 1990s. To call a function, 
you would send a message to another widget. If that widget could handle 
it, it would execute the appropriate message handler. If not, the 
message would fall through to the next level of the message-handling 
hierarchy:


    widget
    card
    background
    window
    application
    interpreter


In Hypercard this was based on a GUI framework, but the principle 
doesn't just apply to GUIs. I think that the Actor model of computation 
is similar.


-- 
Steve
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/XCQEZ3P3DZUTR7PL6RFWR36I6FHX4A5Y/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to