On Oct 27, 2019, at 15:07, Ben Rudiak-Gould <benrud...@gmail.com> wrote:
> 
> throw is an expression, not a statement, in C++. I see no reason raise
> couldn't be an expression in Python. It doesn't even need a special
> rule in the grammar:
> 
>    from __future__ import raise_function
> 
>    foo.setParseAction(lambda a, b, c: raise(MumbleMumble()))

That’s a pretty big breaking change. Every line of code in every library and 
app that raises would have to change to add parens. That was acceptable between 
2.x and 3.x for print, but I don’t think it would be acceptable between 3.8 and 
3.9, or even between 3.8 and 3.11 with a future schedule unless there was a 
really good reason for it.

And there really isn’t. 

Anyone who wants this can do this today:

    def throw(e): raise e

Install it into builtins or import it into all of your modules, and you’re 
done. Meanwhile, all of the library code you use that has raise statements 
continues to work unchanged.

And meanwhile, if you want to change the language to turn raise into an 
expression, why not just turn it into an expression with the same syntax, just 
like with yield somewhere around 2.4? Then all existing code that raises 
exceptions continues to work; only code that relies on the grammar or AST 
breaks (and that’s explicitly allowed to break between versions).

I’m pretty sure you wouldn’t need any change to the bytecodes and ceval loop, 
and only a small change to the codegen part of the compiler, but I can’t be 
sure without actually trying it.

It might be ambiguous to humans, if not to the parser, to do a bare raise in 
some contexts. If so, that can be solved the exact same way as yield. There’s a 
bit of bikeshedding to be done (the grammar for where it can appear doesn’t 
have to be identical to yield_expression, so you can decide, e.g., to ban x = 
raise e as silly and force people to write x = (raise e), or decide that’s 
consenting-adults silliness and no reason to ban it), but I don’t think there’s 
anything difficult beyond getting everyone to agree on your bikeshed color.

> Looking up and calling the raise function would add overhead to every
> explicitly raised exception, but exceptions are so expensive anyway
> that I think it wouldn't be noticeable.

Are you sure about that? Exceptions aren’t nearly as slow as many people seem 
to think; otherwise, Python couldn’t get away with using them all over the 
place internally.

Try this:

    def throw(e): raise e
    builtins.throw = throw
    del throw

    def f():
        try:
            throw(ValueError('spam'))
        except Exception as e:
            return e

    %timeit f()

And then replace the throw call with a raise statement and try again.

I get 1350ns vs. 548ns, and that’s even before subtracting out the time to look 
up and call f and to return e.

I don’t know how much of this is builtin-lookup vs. function calling vs. 
needing more of the code and data caches vs. whatever, and the function calling 
part would get faster if it were a C rather than Python function, but it’s 
still not going to be unnoticeable.

And if you’re thinking maybe this isn’t a good test because maybe CPython is 
able to optimize something because the exception is handled in the same scope 
that raises it, you could check that with dis, or just try this:

    def f(): raise ValueError('spam')
    def g(): throw(ValueError('spam'))
    def h(fun):
        try: fun()
        except Exception(e): pass

Now it’s 1950ns vs. 734ns.

A raise expression, on the other hand, would add no performance cost. 

At any rate, if you really want this, just define that throw function 
yourself—or one that takes a type and *args and **kw and constructs the 
exception, or whatever API you want—and use it in place of raise in your code. 
It’s as trivial a function as could be, and if you don’t raise exceptions in a 
bottleneck, it probably doesn’t matter that you’ve made them more than twice as 
slow to raise, and you won’t be breaking any builtin or library code that 
expects it to be faster because that code is still using raise statements.


_______________________________________________
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/MLH7SZBIA7M6ASRB7UUPSU667ELBCBAC/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to