
On Fri, Feb 17, 2017 at 10:10 PM, Steven D'Aprano <steve@pearwood.info> wrote:
the expression is executed and the delayed expression is replaced with the result. (Thus, the delayed expression is only every evaluated once).
That's easily done by having the "delayed" keyword cache each expression it sees, but that seems like a bad idea to me:
spam = delayed: get_random_string() eggs = delayed: get_random_string() # the same expression
spam.upper() # convert to a real value
assert spam == eggs # always true, as they are the same expression
Worse, suppose module a.py has:
spam = delayed: calculate(1)
and module b.py has:
eggs = delayed: calculate(1)
where a.calculate and b.calculate do completely different things. The result you get will depend on which happens to be evaluated first and cached, and would be a nightmare to debug. Truely spooky action-at-a- distance code.
My understanding is that a single 'delayed expression' will be evaluated at most once. It's more like this: spam = delayed: get_random_string() eggs = spam spam.upper() # At this point, the object becomes a real value assert spam is eggs # always true, as they are the same object Two instances of "delayed:" will create two distinct delayed expressions. The big question, though, is what triggers evaluation. AIUI, merely referencing the object doesn't (so "eggs = spam" won't force evaluation), but I'm not sure what does. Do delayed-expressions have identities or only values? For example: rand = delayed: random.randrange(10) otherrand = rand assert rand is otherrand # legal? randid = id(rand) # legal? print(rand) # force to concrete value assert any(rand is x for x in range(10)) # CPython int caching assert randid == id(rand) # now what? Alternatively, once the value becomes concrete, the delayed-expression becomes a trampoline/proxy to the actual value. Its identity remains unchanged, but all attribute lookups would be passed on to the other object. That does mean a permanent performance penalty though - particularly if it's doing it all in Python code rather than some sort of quick C bouncer. ChrisA