[Python-ideas] pep 312 - implicit lambdas idea

Steven D'Aprano steve at pearwood.info
Sat Aug 8 02:21:15 CEST 2009


On Fri, 7 Aug 2009 10:46:40 pm ilya wrote:
> I was thinking about a good syntax for implicit lambdas for a while
> and today I had this idea: make ``_:`` a shortcut for ``lambda
> _=None:``

[...]

> The rationale is that you only want to get rid of lambda keyword to
> create a *very* simple function, the one that will be called either
> without parameters or with only one parameter. For everything more
> complicated, you really should go and write the explicit function
> signature using lambda.

Why would you want to get rid of the lambda keyword? What's the benefit?

Is this about saving twelve keystrokes?

lambda _=None:
  versus
_:

Just how often do you want, or need, to write such a lambda? It seems to 
me that not only is it a special case you want to break the rules for, 
which goes against the Zen, but it's an incredibly rare special case.

_ as an identifier already has three conventional meanings:

(1) In the interactive interpreter, _ is the value of the last 
expression typed.

(2) It is commonly used to mean "I don't care about this value", e.g. 

t = ("Fred Smith", "123 Fourth Street", "New York", "dog")
name, _, _, pet = t

(3) It is also often used in internationalization.

You want to give it the extra meaning "a default parameter name for 
lambda when I can't be bothered typing even a single letter name".

Because _ is already a valid identifier, this will break code that does 
this:

while _:
    process()
    _ = function()

if _:
    print "something"


Not the best choice of names, but somebody, somewhere, is doing that, 
and your suggestion will break their code.


Looking at the three examples you gave:

map( _: _ + 5, some_list)
register_callback( _: True)
def apply_transform(..., transform = _:_, ... ):

In the first case, I wouldn't use the short-cut form even if it were 
available. I'd write a lambda that used a more meaningful name. In this 
case, I'm expecting an int, so I would use n, or a float, so I'd use x. 
I'd also avoid setting the pointless default:

map(lambda x: x+5, some_list)
  vs
map(_: _+5, some_list)

Since your suggestion doesn't do precisely what I want, the only reason 
I would have for using your construct is to save seven keystrokes. 
Encouraging laziness on the behalf of the programmer is not a good 
reason for special-casing rare cases.

Second case: register_callback( _: True)

I assume you're implying that the callback function must take a single 
argument. In this example, using _ as the parameter name to the lambda 
makes sense, because it is a "don't care" argument. But if the callback 
function is documented as always being given a single argument, I would 
want to know if it was being called without any arguments, so the 
default value of None is inappropriate and I would avoid using it.

Third case: def apply_transform(..., transform = _:_, ... ):

I don't think I'd write a function called apply_transform() which made 
the transformation function optional, let alone buried deep in the 
middle of a whole lot of extra parameters. (I presume that's what 
the "..."s are meant to imply.) But putting that aside, I see your 
intention: a default do-nothing function which appears in a very long 
parameter list. The problem is that instead of trying to shrink the 
default value so you can fit all the parameters on a single line, you 
should make such a complicated function signature more readable by 
spreading it out:

def apply_transform(
    obj,
    start, end,      # start (inc) and end (exc) positions to apply
    another_arg,     # does something very important I'm sure
    x=0, y=1, z=2,   # more very important arguments  
    transform=(      # default null transformation
              lambda obj=None: obj),  
    frotz=False,     # if true, frotz the hymangirator with spangule
    hymangirator=None,
    spangule=None,
    magic=12345,     # this needs no documentation
    namespace={},
    flibbertigibbet=None,
    _private_magic=[]  # the caller shouldn't supply this
    ):

(Even better is to avoid such complicated function signatures, but 
sometimes that's not an option.)

So again I'd be very unlikely to use your suggested construct except out 
of simple can't-be-bothered-to-type-a-dozen-letters laziness. Pandering 
to that sort of laziness is probably not a good thing.

Fundamentally, this suggestion doesn't add expressability to the 
language, or power. Laziness on it's own is not a good reason for 
special casing rare cases. If it was a very common case, then *perhaps* 
you would have an argument for special casing needless verbiage: 
conciseness (up to a point) is a virtue in a language. That's partly 
why we have lambdas in the first place, so we can write this:

reduce(lambda a,b: (a+b)/2.0, somelist)

instead of this:

def average(a, b):
    return (a+b)/2.0
reduce(average, somelist)

But this isn't a common case, it's a rare case, and the case you're 
hoping to replace is pretty concise already.



-- 
Steven D'Aprano



More information about the Python-ideas mailing list