[Python-ideas] Inline Functions - idea

Andrew Barnert abarnert at yahoo.com
Thu Feb 6 13:11:09 CET 2014


On Feb 6, 2014, at 3:14, Nick Coghlan <ncoghlan at gmail.com> wrote:

> On 6 February 2014 20:34, Ron Adam <ron3200 at gmail.com> wrote:
>> On 02/05/2014 08:49 AM, Skip Montanaro wrote:
>>> 
>>> I'm not convinced this particular example needs an inline function.
>>> Just write saveLine() as a normal function and pass in your locals:
>>> 
>>> def f():
>>>     a = 1
>>>     b = 7
>>>     compute(**locals())
>>> 
>>> def g():
>>>     a = 3
>>>     b = 0.9
>>>     compute(**locals())
>>> 
>>> def compute(**args):
>>>     print args["a"] + args["b"]
>>> 
>>> f()
>>> g()
>>> 
>>> That's not to say inline functions might not be handy. It's possible
>>> that you can implement them without modifying the language either. A
>>> peephole optimizer could inline small functions which are used a lot.
>>> 
>>> Skip
>> 
>> 
>> The other day I was trying to figure out how to do lamba calculus without
>> using closures (or other tricks).
>> 
>>>>> def I (x): return x
>>>>> def K (x):
>> ...     return lambda y: x
> 
> This returns a closure.
> 
>>>>> def S (x):
>> ...    return lambda y: lambda z: x(z)(y(z))
> 
> This returns a closure that returns a closure.
> 
>> To do it without closures isn't easy.
> 
> Lambda expressions aren't special from a scoping point of view,
> they're just a different way to write:
> 
>    def <lambda>(*args, **kwds):
>        return expr
> 
> They're only special from a structural point of view (as expressions,
> you can put them in places where full functions aren't allowed).
> 
> As far as what you're proposing goes, is it essentially a way to
> declare a function like (spelling out the lambdas fully):
> 
>    def S(x):
>        def _second(y):
>            def _third(z):
>                return x(z)(y(z))
>            return _third
>        return _second
> 
> As something much shorter like this:
> 
>    def S (x)(y)(z):
>        return x(z)(y(z))

I think his point is that he wants it to be implemented _without_ closures--or at least as a single closure, with the same scope shared by all of the functions instead of three scopes and closure cells linking them together.

Personally, I'm not sure what that adds; I'm just raising what I think is someone else's point. There could conceivably be performance benefits, but then again, there could also be a cost to keeping alive an entire scope when you don't need everything. Other than that, the visible effect would be exactly the same as with your explicit closure version.

> The main potential benefit

I think the arguable brevity and readability benefit is the main potential benefit here, as your decorator example. If the abbreviated examples are clearer, the idea is a win even without the pickling; if it's more of an attractive nuisance that makes it easier to write impenetrable code more than it makes it easier to write simpler code, the idea isn't worth doing even with the pickling.

> I could see to a construct like that is
> that it may allow the more consistent creation of closures that
> support pickling, since the outer functions are guaranteed not to have
> any side effects and to have argument capture as their *only*
> significant state. This means that you could take the inner function,
> pickle it along with its closure variables and reconstruct that at the
> far end, only relying on the name of the outer function.

Out of curiosity, how would you implement that? Right now, functions don't reduce, and pickle just stores their global name. Would you make pickle detect side-effect-free closures (by way of a flag exposed via inspect or something?), dig out the arguments to the outer function, and pickle them as calls with a new opcode similar to new-style class instances? Or change functions so they can reduce themselves in appropriate circumstances?

> Such a construct could also make decorator factories easier to write.
> 
>    def decorator(f):
>        # Do something with f
> 
>    def decorator_factory(some, args, here)(f):
>        # Do something with f, but have access to the bound args.
> 
> There's an argument to be made that the extra parens in the function
> header are too easy to miss, but I still see "make it easier to write
> side-effect free closures" as an idea worth discussing further.

I like this idea, and your syntax. With or without collapsing frames or doing anything special (like pickling) with the results.


More information about the Python-ideas mailing list