[Python-ideas] One more time... lambda function <--- from *** signature def.

Masklinn masklinn at masklinn.net
Tue Mar 4 13:50:19 CET 2014


On 2014-03-04, at 13:07 , Chris Angelico <rosuav at gmail.com> wrote:
> On Tue, Mar 4, 2014 at 10:09 PM, Steven D'Aprano <steve at pearwood.info> wrote:
>> Agreed. What I have in my head is some vague concept that the Python
>> evaluation rules will somehow know when to evaluate the thunk and when
>> to treat it as an object, which is (as I understand it) what happens in
>> Algol. Again, just thinking aloud, perhaps we do this:
>> 
>> thunk = `some_expression`  # delays evaluation
>> a = [0, 1 + thunk]  # evaluates thunk in the current scope
>> b = [0, `1 + thunk`]  # delays evaluation and creates a thunk object
>>                      # equivalent to `1 + some_expression`
>> c = b[1]  # now evaluates the thunk object
>> d = f(2, thunk)  # evaluates thunk in f's scope
>> e = g(3, `thunk`)  # passes the un-evaluated thunk object to g
>> 
>> Consider this just a sketch, and in no way fully thought out.
>> 
>> (This will most definitely need a PEP.)
> 
> PEP can come later. First, let's get some solid use-cases, and start
> looking at implications. The way it's described here, there's
> effectively magic when you try to look at an object of this type,
> which will break a lot of assumptions. Most people expect that:
> 
> foo = bar
> assert foo is bar
> 
> to be a safe assumption, but if bar is a thunk, then it's getting
> evaluated separately in each of those

Why? Either it's forced during assignment or both names map to
the same thunk, and are both forced when any of them is.

That could be during the identity check, but since both names refer to
the same thunk they can only yield the same value, so the identity check
needs not force the thunk. An equality test would likely force the
thunk.

> so that
> might cause confusion. But you could always special-case it: writing
> `thunk__` will be guaranteed to transmit the thunk unchanged, and if
> you actually mean to add another wrapper layer, use `(thunk__)` or
> something instead.

Is there a use case for actually thunking a thunk?

> The biggest thing to figure out is scoping. Does a thunk take a
> snapshot of its enclosing scope (a closure), or is it an expression
> that gets evaluated in the target namespace? The latter could be
> extremely confusing, but the former's just what a nested function
> does, so this'd just be a new lambda syntax.

That is essentially what a thunk is, at least in my experience: it is
conceptually a nullary memoized function, forced (evaluated/called) if
an actual value/object is ever needed but potentially thrown out during
reduction. The difference, under the proposed semantics, is that the
forcing of the thunk would be implicit where that of a function is
explicit (not sure that's a good idea in a strict language).


More information about the Python-ideas mailing list