A few points for clarity:

Yes, I would expect each instance of delayed to result in a new delayed 
expression, without caching, except for multiple calls to that same delayed 
expression instance. 

Also, I suggested the colon : because unlike async/await, the following 
expression is NOT executed at the time delayed is executed. The only other ways 
to do this on Python I know of are def and lambda, both of which use colons to 
highlight this. 

As for what triggers execution? I think everything except being on the right 
side of an assignment. Even identity. So if a delayed expression would evaluate 
to None, then code that checks is None should return true. I think this is 
important to ensure that no code needs to be changed to support this feature. 

So for Chris: yes, rand is otherrand not because the delayed instances are the 
same, but because the value under them is the same, and the is should trigger 
evaluation. Otherwise code would need to be delayed aware. 

Finally as for the word delayed. Yes, it could be a symbol, or existing 
keyword, but I have no suggestions on that front. 

-Joseph

> On Feb 17, 2017, at 6:21 AM, Chris Angelico <ros...@gmail.com> wrote:
> 
> On Fri, Feb 17, 2017 at 10:10 PM, Steven D'Aprano <st...@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
> _______________________________________________
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to