Hi all, If we want this it might be interesting to investigate what the Scheme community has been doing, since they have had this (under the name "promises") for many years.
Basically: Scheme: (delay expr) <=> proposed Python: delayed: expr The Scheme community has experimented with what they call "auto-forcing", i.e. a promise can be given to any primitive operation and is then forced. However this has not caught on. Possibly for a good reason ;-) (My gut feeling: too much magic. Explicit is better than implicit.) Note that Racket/PLT Scheme has also "lazy" in addition to "delay". The rationale for this is given in: "How to add laziness to a strict language without even being odd", Philip Wadler, Walid Taha, David MacQueen https://www.researchgate.net/publication/2646969_How_to_Add_Laziness_to_a_Strict_Language_Without_Even_Being_Odd It would be good to read and consider this before we reinvent the square wheel ;-) Stephan 2017-02-17 10:14 GMT+01:00 David Mertz <david.me...@gmail.com>: > Agreed. But there might be cases where something occurring at most one—at > some unspecified time—is desirable behavior. In general though, I think > avoiding side effects should be programming recommendations, not anything > enforced. > > This model isn't really so different from what we do with asyncio and its > "call soon" indeterminate order. > > On Feb 17, 2017 1:07 AM, "Joseph Jevnik" <joe...@gmail.com> wrote: > >> Even with the new syntax I would highly discourage delaying a function >> with observable side effects. It would make reasoning about the behavior of >> the program very difficult and debugging becomes much harder. >> >> On Fri, Feb 17, 2017 at 3:31 AM, David Mertz <me...@gnosis.cx> wrote: >> >>> I had forgotten about Daisy! It's an interesting project too. The >>> behavior of 'autodask()' is closer to what I'd want in new syntax than is >>> plain dask.delayed(). I'm not sure of all the corners. But is definitely >>> love to have it for expressions generally, not only pure functions. >>> >>> On Feb 17, 2017 12:03 AM, "Joseph Jevnik" <joe...@gmail.com> wrote: >>> >>>> You can let dask "see" into the function by entering it and wrapping >>>> all of the operations in `delayed`; this is how daisy[0] builds up large >>>> compute graphs. In this case, you could "inline" the identity function and >>>> the delayed object would flow through the function and the call to identity >>>> never makes it into the task graph. >>>> >>>> [0] http://daisy-python.readthedocs.io/en/latest/appendix.html#d >>>> aisy.autodask >>>> >>>> On Fri, Feb 17, 2017 at 2:26 AM, David Mertz <me...@gnosis.cx> wrote: >>>> >>>>> On Thu, Feb 16, 2017 at 11:15 PM, David Mertz <me...@gnosis.cx> wrote: >>>>>> >>>>>> This also means that a 'delayed' object needs to be idempotent. So >>>>>> >>>>>> x = delayed 2+2 >>>>>> >>>>>> y = delayed x >>>>>> >>>>>> z = delayed delayed delayed y >>>>>> >>>>>> >>>>>> Wrapping more delays around an existing delayed object should >>>>>> probably just keep the same object rather than "doubly delaying" it. If >>>>>> there is some reason to create separate delayed objects that isn't >>>>>> occurring to me, evaluating 'z' would still go through the multiple >>>>>> evaluation levels until it got to a non-delayed value. >>>>>> >>>>> >>>>> This is sort of like how iterators "return self" and 'it = iter(it)'. >>>>> >>>>> In the case of Dask, wrapping more delayed objects creates layers of >>>>> these lazy objects. But I think it has to because it's not part of the >>>>> syntax. Actually, I guess Dask could do graph reduction without actual >>>>> computation if it wanted to. But this is the current behavior: >>>>> >>>>> >>> def unchanged(x): >>>>> ... return x >>>>> >>> a = delayed(unchanged)(42) >>>>> >>> a >>>>> Delayed('unchanged-1780fed6-f835-4c31-a86d-50015ae1449a') >>>>> >>> b = delayed(unchanged)(a) >>>>> >>> c = delayed(unchanged)(b) >>>>> >>> c >>>>> Delayed('unchanged-adc5e307-6e33-45bf-ad73-150b906e921d') >>>>> >>> c.dask >>>>> {'unchanged-1780fed6-f835-4c31-a86d-50015ae1449a': (<function >>>>> __main__.unchanged>, >>>>> 42), >>>>> 'unchanged-adc5e307-6e33-45bf-ad73-150b906e921d': (<function >>>>> __main__.unchanged>, >>>>> 'unchanged-c3282bc4-bdaa-4148-8509-9155cac83ef0'), >>>>> 'unchanged-c3282bc4-bdaa-4148-8509-9155cac83ef0': (<function >>>>> __main__.unchanged>, >>>>> 'unchanged-1780fed6-f835-4c31-a86d-50015ae1449a')} >>>>> >>>>> >>> c.compute() >>>>> 42 >>>>> >>>>> >>>>> Actually Dask *cannot* know that "unchanged()" is the function that >>>>> makes no transformation on its one parameter. From what it can see, it's >>>>> just a function that does *something*. And I guess similarly in the >>>>> proposed syntax, anything other than a plain name after the 'delayed' >>>>> would >>>>> still need to create a new delayed object. So it's all an edge case that >>>>> doesn't make much difference. >>>>> >>>>> -- >>>>> Keeping medicines from the bloodstreams of the sick; food >>>>> from the bellies of the hungry; books from the hands of the >>>>> uneducated; technology from the underdeveloped; and putting >>>>> advocates of freedom in prisons. Intellectual property is >>>>> to the 21st century what the slave trade was to the 16th. >>>>> >>>> >>>> >> > _______________________________________________ > 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/