Thanks for the elaboration.
Lazy evaluation
This first thing I note is the inclusion of lazy evaluation.
The original PEP makes no mention of lazy evaluation. This is a very large addition.
Adding lazy evaluation changes the PEP enough that it should be fully reconsidered.
I note that your PR is titled “Lazy evaluation and other small changes”
Adding lazy evaluation is no small change.
Lazy evaluation is complex and subtle; just see the many and long discussions around PEP 649.
New scope(s)
It isn’t clear from your hidden functions what the scope rules are, and how many new scopes are being added.
You state that only one new scope is being added, so assuming that’s true, let’s suppose a let
syntax.
let var = value:
Where var
would shadow var
s in enclosing scopes, but other variables have their normal scope, such that:
x = "outer"
let x = "inner":
y = "hi from inner"
print(x)
print(x)
print(y)
would produce
"inner"
"outer"
"hi from inner"
Just to be clear, I am not proposing adding a let
keyword, I’m just using it to express the semantics.
So, using the imaginary “let”, and without lazy evaluation:
class Cls[T](Base):
def method(self) -> T: ...
becomes
let T = TypeVar("T"):
class Cls(Base, typing.Generic[T]):
__type_params__ = (T,)
def method(self) -> T: ...
and
def func[T](arg: T) -> T: ...
becomes
let T = TypeVar("T"):
def func(arg: T) -> T: ...
func.__type_params__ = (T,)
It should be possible to define all the new syntax in terms of a single, simple, new scope (which doesn’t have to be what I describe above).
Otherwise, it is just too complicated.
Conclusion
The inclusion of lazy evaluation definitely means that the PEP should be deferred to 3.13.
We need to consider how to approach lazy evaluation, so that it works for all use cases:
PEP 649, PEP 695, possible lazy imports, and other uses.
If lazy evaluation were dropped from the PEP, then I still think it should be deferred.
If it absolutely must go for in 3.12, for whatever reason, then the following needs to happen:
- Drop lazy evaluation
- Specify the behaviour using explcit scope notation (as described above)
But, why the mad rush?
Regardless of what happens for 3.12, later versions will be better for a less rushed design and implementation.