On Fri, Apr 08, 2022 at 08:24:40AM +0000, Malthe wrote:

> But firstly, let me present the idea. It is very simple, that Python
> should have declarative imports, 

I'm not sure I understand why you consider this "declarative".

https://en.wikipedia.org/wiki/Declarative_programming

As I see it, this proposal merely adds a unary operator for implicit 
imports.



> For example, `some_regex = @re.compile(...)`.
> 
> What happens then is that before anything else in that module, that
> symbol is imported:
> 
>     from re import compile as _mangled_re_compile
> 
> It must be the very first thing (hoisting) because when else would it
> happen?

On-demand. As you say yourself, this could be a dynamic import at the 
time of use.


> It's been suggested before to have a shorthand syntax which
> does a dynamic import at the time of using it but this brings me to
> the twist:
> 
> We want typing to pick up these imports.

At the moment static type checkers have to look for two import 
statements: `import spam`, and `from spam import eggs`.


With this proposal, they will still need to look for those two import 
statements, but they will also need to parse every expression looking 
for `@` as a unary operator:

    result = 2*x**3 - 3*y + @math.sin(x*y) - 5*x*y**2

This does not help typing at all. It just means the type-checker has to 
do more work to recognise imports.



> And this twist has a second
> leg which is that we often need to import symbols simply in order to
> type some argument type or return type. This leads to a great many
> more imports to type.

Code is read much more than it is written. I would much prefer to have 
explicit imports (by convention, if not necessity) in one place at the 
top of the page, than to mystery symbols where the implicit import could 
be buried far away.

Right now, this is an error:

    # Start of module.
    obj = wibble.foo

because wibble is not a built-in nor a global (excluding weird 
shenanigans committed by other modules), so the name "wibble" doesn't 
exist. But with hoisting, that import could be *anywhere* in the file. 
Even in dead code.

    # Start of module.
    obj = wibble.foo
    ...
    ...
    # five pages of code later
    for a in obj.method():
        while flag:
            if condition:
                @wibble

That's right, with hoisting you can use a module before you import it. 
Mind. Blown.

Have pity on beginners, casual Python programmers, and the people who 
have to help them. Don't implement this horror.

If it were merely on-demand imports, then we would know that the import 
@wibble would have to appear in actual, executed code before you can use 
wibble. But with hoisting, we don't even have that promise.

It is truly spooky action at a distance. And to save nothing but an 
import line.


> A situation where this would come in really handy is in scripting such
> as how we use Python in Apache Airflow to let users write out simple
> workflows. A workflow definition which could be a 5-liner quickly
> becomes a 20-liner – consider for example:
> 
>     default_args = {
>         "start_date": @datetime.datetime(...)
>     }

That's just a three-liner, which becomes a four-liner:

    import datetime
    default_args = {
        "start_date": datetime.datetime(...)
    }



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

Reply via email to