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

Ron Adam ron3200 at gmail.com
Fri Feb 28 20:42:57 CET 2014



On 02/28/2014 11:54 AM, Chris Angelico wrote:
> On Sat, Mar 1, 2014 at 4:17 AM, Ron Adam<ron3200 at gmail.com>  wrote:
>> >This returns a lambda-like function.
>> >
>> >       def star_lambda(***expr): return expr
>> >
>> >
>> >And is used this way...
>> >
>> >       result = star_lambda(a * b + c)  # captures expression.
>> >
>> >       actual_result = ***result        # *** resolves "result" here!
>> >
> Interesting, but I don't like the way the interpretation of a function
> call depends on the target function. With both * and ** notations,
> there's absolutely no difference: the function is called with these
> positional and those keyword arguments, whether they came from actual
> args or from * or ** unpack/repacks;and there's no difference between
 > a function that collects args with *args,**kwargs and one that
 > collects them with individual names (or a C-level function that might
 > do something altogether different).


It's not clear what differences you mean here... can you show some examples?



I think we just are used to not thinking about it, But it's not really that 
different.

         def fn(*args, **kwds): ...

This wraps args in a list, and kwds in a dict.  It's up to the *function 
called* to do what is intended by the syntax.


        def fn(*args): ...

        fn(a, b, c)  -->   fn(list(a, b, c))    #depends on function called.



        def fn(**kwds): ...

        fn(a=1, b=2, c=3)  -->  fn(dict(a=1, b=2, c=3))  # here too.


         def fn(***expr): ...

         fn(expr)   -->   fn(TriStar(lambda:(expr)))

         # A bit more complex, but also the same.
         # Parentheses need to capture tuple packing
         # due to ',' having a higher precidence.



The mechanism behind each of these may be somewhat different, but there are 
also similarities.


        def fn(***expr): return ***expr


With these, it forwards the these existing cases nicely.

        a, b, c = fn(a, b, c)

        args = fn(*args)args, kwds

        kwds = fn(**kwds)

        args, kwds = fn(*args, **kwds)


And just like '**' can't be used to pack a dictionary directly, we can't 
use '***' to pack an expression directly.

Using "**" in a funciton unpacks the dictionary.

Using "***" in a function call expresses the TriStar object.


     (* any name for the TriStar object would work.  (small detail))



NOW here is the main limitation... :-/

        a, b, c = fn(a, b, c=1)

Which is because (a, b, c=1) isn't a valid expression outside of a function 
call.  Or should this be captured as (a, b, {"c":1})?

Sigh... darn edge cases.  A bit more than an edge case I think.

Any ideas?


Cheers,
    Ron













































> With this proposal, your
> star_lambda function's declaration changes the call site - instead of
> evaluating a*b+c, it has to construct an anonymous function and pass
> it along.







More information about the Python-ideas mailing list