I know, lambda bashing (and defending) in the group is one of the most
popular ways to avoid writing code. However, while staring at some Oz
code, I noticed a feature that would seem to make both groups happy -
if we can figure out how to avoid the ugly syntax.
This proposal does away with the well-known/obscure "lambda"
keyword. It gives those who want a more functional lambda what they
want. It doesn't add any new keywords. It doesn't add any new magic
characters, though it does add meaning to an existing one. That could
be replaced by a new magic token, or adding magic meaning to a
non-magic token. It breaks no old code either way.
I haven't really worked out all the implications; I just wanted to
throw it out and see what everyone else thought about it. As a
result, the code examples tend to be ugly.
As previously hinted, this feature is lifted from Oz.
Currently, class and functions definitions consist of a keyword -
either "class" or "def" - followed by a name, a header, then code. The
code is compiled into an object, and the name is bound to that object.
The proposal is to allow name to be a non-name (or rare name)
token. In this case, the code is compiled and the resulting object is
used as the value of the class/def expression.
My choice for the non-name token is "@". It's already got magic
powers, so we'll give it more rather than introducing another token
with magic powers, as the lesser of two evils.
Rewriting a canonical abuse of lambda in this idiom gives:
myfunc = def @(*args):
return sum(x + 1 for x in args)
If you remove the '@' -- which is not really needed -- you have exactly my (at least
I think it was mine -- the variation are, in any case ;-) old anonymous def proposal.
So good luck in getting any more favorable attention than I did ;-)
I've also proposed named and anonymous callable local blocks for
the other variations of removing 'def' and/or the binding name from
normal def syntax. E.g.,
def my_func(*args): # normal def
return sum(x + 1 for x in args)
my_func = def(*args): # anonymous def expression
return sum(x + 1 for x in args)
my_local_callable_block(*args): # named local callable block
nargs = len(args) # binds nargs as if this suite were e.g. an "if" suite.
return sum(x + 1 for x in args)
my_local_callable_block = (*args): # local callable block expression
nargs = len(args) # binds nargs as if this suite were e.g. an "if" suite.
return sum(x + 1 for x in args)
The local callable blocks can be made accessible via a dict or list or whatever and called like
lcb_dict[key](args)
to have the bindings occur in the scope of the block definition. This avoids the problem of
the typical case dispatch of function calls via a dict, where the function has its own temporary
local namespace and binding in the calling namespace is kludgey.
In other words, this is identical to:
def myfunc(*args):
return sum(x + 1 for x in args)
We can write the same loop with logging information as:
sum(def @(arg):
print "Bumping", arg
return arg + 1
(x) # '(' at the same indent level as def, to end the definition
for x in stuff)
You are almost quoting me in previous posts (protesting that the indentation "problem" is no big deal ;-)
A more useful example is the ever-popular property creation without
cluttering the class namespace:
class Spam(object):
myprop = property(fget = def @(self):
return self._properties['myprop']
,
fset = def @(self, value):
self._properties['myprop'] = value
,
fdel = def @(self)
del self._properties['myprop']
,
doc = "Just an example")
Again, the '@' is not necessary ;-)
This looks like the abuse of lambda case, but these aren't
assignments, they're keyword arguments. You could leave off the
keywords, but it's not noticably prettier. fget can be done with a
lambda, but the the others can't.
Well, they can, but it's not pretty ;-)
Giving clases the same functionality seems to be the reasonable thing
to do. It's symmetric. And if anonymous function objects are good,
then anonymous class objects ought to be good as well.
I agree.
Regards,
Bengt Richter