Sorry, accidentally off-list. Here it is again.

On Fri, Dec 10, 2021 at 4:50 PM Christopher Barker <pythonchb@gmail.com> wrote:
Thanks Eric, this is a great example, thanks. 

It does raise some questions. Though.

If we could use any expression as a deferred expression, then we still have the two key questions:

When does it get evaluated, and what namespaces does it use? 

@dataclasses.dataclass
class A:
    my_list: list = dataclasses.field(default_factory=list)

What I'd like to be able to say:

@dataclasses.dataclass
class A:
    my_list: list = `[]`

I think in the data classes case, you could clearly define both of those. But in the general case?

def fun(n):
    return `len(n)`

@dataclasses.dataclass
class A:
    length: n = fun()

What would that put in the signature? What namespace would the express e evaluated in? 

Yes, that is completely contrived, but it does bring up the complications of a “general” solution. 

Maybe we could solve the dataclass problem with late bound class attributes:

@dataclasses.dataclass
class A:
    length: n => len(n)

Though I suppose that would still get evaluated before the dataclass decorator would see it :-(

Side note: I wonder if dataclasses could be a bit smarter for the common. case: if the type is a callable, and the value is a particular Sentinel, the. Call it to get the default:

@dataclasses.dataclass
class A:
    my_list: list = dataclasses.Empty

That would work for most of the cases where I need to use field explicitly.

- CHB 




In the class A, before @dataclass is called, I want A.my_list to be a "deferred object" that I could then use when @dataclass is generating __init__(). Exactly how and when the "deferred object" would get evaluated is debatable, but not so important for the sake of this discussion. Suffice it to say that it would either be explicitly or implicitly evaluated at the start of __init__.

I think you can see that this would benefit from similar functionality to late-bound parameters, and that if we had this more general mechanism that late-bound parameters could use the same underlying mechanism.

And in case I wasn't clear: to get the late-bound parameter functionality using this syntax, you'd use:

def foo(my_list = `[]`):

That's why I think we should have a larger concept that just late-bound parameters: I think there's a general concept here that can be extended beyond parameters. And that's why I thing not restricting it to a function-definition-only syntax is important: we should produce a syntax that can be used in more places than just functions. This is why I think we need to decide on this larger scope before accepting the narrow function-definition-only syntax: if we decide to add "deferred objects" later, we'd have two ways to specify late-bound parameters [0].

Eric

[0]: Or arguments, I can never remember which is which: someone needs to invent a memorable mnemonic device.

Had these "deferred objects" existed when I designed dataclasses, I would have used them instead of the clunky default_factory. PEP 671 does not help with this use case, where a late-bound parameter isn't specified in a function definition. I need the late-bound parameter to be stored in an object I can refer to later.

Eric

_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-leave@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/T62V6IMOJDADAFWJ2DIAS4WHJQMI4CHU/
Code of Conduct: http://python.org/psf/codeofconduct/
--
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
--
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython