[Python-ideas] Delayed Execution via Keyword
David Mertz
mertz at gnosis.cx
Sun Feb 19 12:31:27 EST 2017
On Sun, Feb 19, 2017 at 8:24 AM, Michel Desmoulin <desmoulinmichel at gmail.com
> wrote:
> A great proposal, although now I would have to explain to my students
> the subtle difference between:
>
> res = (print(i * i) for i in range(x))
> res = delayed [print(i * i) for i in range(x)]
> They seems doing something similar, but they really don't.
Well, at the introductory level they are kinda similar. I know the
mechanism would have to be different. But at a first brush it's the
difference between delaying the whole concrete collection and delaying one
item at a time. That wouldn't be terrible for a first Compsci lesson.
> def stuff(arg=delayed []):
>
> Does this mean we create a NEW list every time in the body function ? Or
> just a new one the first time than the reference stays in arg ?
>
I think this cannot make a new list each time. Of course, I'm one of those
people who have used the mutable default deliberately, albeit now it's
mostly superseded by functools.lru_cache().
But the idea of a "delayed object" is one that transforms into a concrete
(or at least *different* value) on first access. In a sense, the
transformation from a delayed object to an iterator is still keeping it
lazy; and clearly `x = delayed my_gen()` is a possible pattern.
The pattern of `def stuff(arg=delayed expensive_computation(): ...` is
important to have. But as in my longer example, `arg` might or might not
be accessed in the function body depending on condition execution paths.
Still, once `expensive_computation()` happens one time, that should be it,
we have a result. Obviously `list()` is not an expensive operation, but
the syntax cannot make a boundary for "how costly."
> The "delayed" keyword sounds a lot like something used in async io, so I
> like "lazy" much more. Not only it is shorter, but it convey the meaning
> of what we are doing better.
>
I like `lazy` too.
> a = (await|yield) lazy stuff
> a = lazy (await|yield) stuff (should it even allowed ?)
> a = (lazy stuff(x) for x in stuff)
>
a = lazy f'{name}' + stuff(age) # is there a closure where we store "name"
> and 'age'?
I don't quite have a clear intuition about how lazy/delayed and
await/yield/async should interact. I think it would be perfectly
consistent with other Python patterns if we decided some combinations
cannot be used together. Likewise you can't write `x = await yield from
foo`, and that's fine, even though `yield from` is an expression.
> First, if there is an exception in the lazy expression, Python must
> indicate in the stack trace where this expression has been defined and
> where it's evaluated.
>
Yes. I mentioned that there needs to be *some* way, even if it's an ugly
construct, to find out that something is delayed without concretizing it.
I think the best idea is hinted at in my preliminary thought.
I.e. we can have a special member of a delayed object that does not
concretize the object on access. So maybe `object._delayed_code` of
something similar. Since it's the interpreter itself, we can say that
accessing that member of the object is not a concretization, unlike
accessing any other member. Every object that is *not* a delayed/lazy one
should probably have None for that value. But delayed ones should have, I
guess, the closure that would get executed on access (then once accessed,
the object becomes whatever the result of the expression is, with
`._delayed_code` then set to None on that transformed object).
> a = lazy stuff
> if a is not lazy:
> print(a)
>
So my spelling would be:
a = lazy stuff
if a._delayed_code is not None:
print(a)
> One last thing: my vote is not dropping the ":" in front of they keyword.
>
I think the colon has parser problems, as I showed in some examples. Plus
I don't like how it looks. But I'd much rather have `a = lazy: stuff` than
not have the construct at all, nonetheless.
--
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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20170219/b447da2d/attachment.html>
More information about the Python-ideas
mailing list