Hi Julia,

On Fri, Apr 16, 2021 at 11:00 AM Jukka Lehtosalo <jlehtosalo@gmail.com> wrote:

If the RHS is a function call, we'd call the function at runtime, but arguments would be (partially) stringified/lazy and they can contain type syntax (I'm glossing over some details):

  type N = NewType(int)
  type T = TypeVar(bound=(int) => str)  # Type-specific syntax is ok
  type D = typing.TypedDict({"x": C})  # C can be a forward reference!
  class C: ...


Note that the results here are usable in runtime contexts, since we call the function:

  x = N(2)  # Ok

My main question about the details of your proposal is this piece. Partial laziness adds a lot of complexity both to implementation and simply to understanding the semantics; is it really necessary? Might it not be acceptable to say that `x = N(2)` can only occur after any forward references involved in the definition of `N` have been defined? (In the common cases I think it would occur inside functions; the ordering is only really an issue if it occurs at top level.) And if so, could we avoid the complexities of partial laziness and instead just always wrap the entire RHS in lazy evaluation?

The other issue is implicitly passing the stringified name as first arg. Personally I would rather handle the lazy evaluation in a generalized way as something like “module level descriptors”, in which case the name issue could be handled via the existing `__set_name__` protocol instead. 

Overall I like the direction of the proposal, and agree that a more holistic solution to handling of type syntax at runtime is needed. 

Carl