[Python-ideas] except expression
spir
denis.spir at gmail.com
Thu Feb 13 19:30:08 CET 2014
On 02/12/2014 10:02 PM, Ram Rachum wrote:
> Hi,
>
> Here's an idea that would help shortening code. Allow a ternary expression
> based on except, like so:
>
> first_entry = entries[0] except IndexError else None
> item = my_queue.get() except queue.Empty else None
> response_text = request('http://whatever.com').text except HttpError
> else "Can't access data"
>
> Aside from the fact that this would be a big grammar addition, a big
> problem here is the usage of the `else` keyword, that when used with except
> usually means "what would happen if there wasn't an exception" and here
> means the opposite. But I couldn't think of a nicer syntax.
>
> I realize that this is a big change and that most people would be opposed
> to this... But I guess I just wanted to share my idea :)
After some considerations, it seems we reached the point of generalising the
idea to:
* provide a builtin way to indicate a special value for the special cases where
the standard value's expression would raise an exception
As Nick Coghlan shows in another post, this is in fact close to a builtin way to
deal with potentially failing functions, in general (below 'op'):
def _helper(op, exc, make_default):
try:
return op()
except exc:
return make_default()
x = _helper(op, Exception, make_default)
However, this only applies to the case of functions properly speaking (which
purpose is computing a product). What about 'actions', meaning procedures that
perform an effect? Take the case of count-words for instance, where (in python)
when encoutering a word one would add 1 to its count in a dict which keys are
the words. On first encounter, there no entry yet for that word. We could check
"word in word_counts", but this is doing the dict lookup twice; and catching an
exception is worse.
The problem I guess, here and also similarly for functions, is that there is no
way for the _client_ (the caller) to control exception throwing; while only the
caller knows whether the failing case actually is an error or not, meaning
belongs or not the application's logics. Maybe what we need is in fact something
like:
maybe statement
[then
dependant-block]
else
alternative-block
This is similar in form to exception catching except (sic!) that the actual
meaning is to _avoid_ an exception, not to catch it (to avoid it beeing thrown
at all). More or less the opposite, in fact. The consequence is that in case of
failure no exception is raised, instead the alternative 'else' branch is taken.
Such a construct would work fine for both called actions and functions (which
calls are expressions in statement). [1]
[Similar considerations are evoked in other languages, especially D where I
first met them. Generally speaking, people start to realise the seamntic
weakness of typical exception catching mecanisms which let no choice or control
in the hands of the one who actually knows, namely the client.]
d
[1] Practically, this just means adding a test before throwing, and setting a
flag instead (the carry would do the job nicely, since it can have no meaning on
func return, and is the only copy flag one can set arbitrarily).
Thus, the above code translates to:
statement
if flag:
reset flag
alternative-block
[else:
dependant-block]
More information about the Python-ideas
mailing list