What c.l.py's opinions about Soft Exception?
Diez B. Roggisch
deets at nospam.web.de
Tue Mar 11 13:00:50 EDT 2008
> If you passed an object that has several methods to call (using tuple
> or list) and you want to handle several softexceptions and ignore some
> others, you must still pass an empty methods to the one you want to
> ignore, cluttering the caller's code by significant degree:
>
> def somefunc(a, b, callback = (DO_NOTHING, DO_NOTHING, DO_NOTHING,
> DO_NOTHING)):
> if a == 0: raise callback(0)
> try:
> a += b
> except ZeroDivisionError:
> raise callback(1)
> if a <= 0: raise callback(2)
> raise callback(3)
> return a
>
> somefunc(a, b, (callbackzero, DO_NOTHING, callbacktwo,
> DO_NOTHING))
You misunderstood. I'd pass something like a context-object, which wold look
like this:
def somefunc(a, b, context=NullContext()):
if a == b: context.a_equals_b()
....
Not more clutter than with only one callback. And the NullContext-object
would actually serve as documentation on what events the code produces.
>> def toplelevel():
>> def callback(a, b):
>> if a == b:
>> raise InterruptException()
>> try:
>> work(callback)
>> except InterruptException:
>> pass
>>
>> def work(callback=callback):
>> a = 10
>> b = 20
>> callback(a, b)
>
> That's why I said most things that can be more cleanly handled by
> SoftException can usually be handled in other forms, although in a
> more cluttered way.
>
> That could be more cleanly written in SoftException as:
> def work():
> a = 10
> b = 20
> raise Equal(a, b)
>
> def toplevel():
> try:
> work()
> except Equal, args:
> a, b = args
> if a == b:
> raise InterruptException
I totally fail to see where
raise Equal(a, b)
is less cluttered or not than
callback(a, b)
Actually, the latter is even less cluttered, misses a raise - if pure number
of literals is your metric, that is.
> If there is a syntax support, you could also make "resume" able to
> transfer values:
>
> def somefunc(a, b):
> if a == b: a, b = raise Equal(a, b)
>
> def toplevel():
> try:
> somefunc(10, 20)
> except Equal, args:
> a, b = args[0], args[1] + 1
> resume a, b
Sure, you can make all kinds of things, but so far you didn't come up with a
comprehensive feature description that just _does_ specify what SEs are and
what not.
> Perhaps you meant:
> raise_soft(SoftException)
>
> cause SoftException() may have side effects if called greedily
Nope, I didn't, and it's beside the point.
> That could be done, but when raise_soft() returns, it returns to the
> code that raises it so it must be 'break'en:
>
> def caller(a, b):
> if a == b:
> raise_soft(SoftException)
> break
>
> but this makes SoftException must break everytime, which make it lost
> its original purpose, so you have to add return code to raise_soft
> whether you want to break it or not:
You didn't understand my example. If there is a handler registered, it will
be invoked. If not, nothing will be raised. The exact same amount of
state-keeping and lookups needs to be done by the SE-implementation.
> That could be done, but when raise_soft() returns, it returns to the
> code that raises it so it must be 'break'en:
> def caller(a, b):
> if a == b:
> if raise_soft(SoftException):
> break
>
> Compare to:
> def caller(a, b):
> if a == b:
> raise SoftException
>
> And this also makes it impossible to have state-changing behavior
> without some other weirder tricks
That's not true. The
with add_soft_handler(SoftException, handler):
approach (I missed the handrel the first time, sorry)
can easily throw an exception to interrupt, like this:
def handler(e):
if some_condition_on_e(e):
raise InterruptException()
with add_soft_handler(SoftException, handler):
try:
work(...)
except InterruptException:
pass
You could also introduce a function
def interruptable(fun, *args, **kwargs):
try:
return fun(*args, **kwargs)
except InterruptException:
pass
to make the code look a bit cleaner - if it fits your usecase, that is of
course.
I don't say that SoftExceptions can't have semantics that go beyond this. I
just don't see a oh-so-compelling use-case that makes things so much better
than they are reachable now, without actually much programming.
Diez
More information about the Python-list
mailing list