[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