Re: Lambda binding solved by lateral thinking?

Tim Peters (tim@ksr.com)
Wed, 02 Mar 94 03:52:59 EST

> > [steve]
> > Also: I think CSNS could be disastrous combined with Python's
> > "create it if it ain't there" assignment and lack of declarations!
> [guido]
> I guess this means death for CSNS in Python then.

There are certainly murky issues to wrestle with, but if you really want
CSNS I bet Steve & I could tolerate trying to be helpful.

> I tried pretending that "global" wasn't needed for a long time but I
> was wrong. In analogy, CSNS will require a corresponding extension to
> global

Agree that CSNS requires a way to bind/rebind non-locals.

> but I don't think a reasonable syntax exists. (No need to propose
> "func.attr" where "func" is an outer function, since "func" evaluates
> to a function object and already has attributes...)

Implying that func.name is not a reasonable syntax but "global varlist"
is. So how about "nonlocal varlist", meaning that a variable belongs to
the smallest containing block that has a local variable with the same
name (& if there is none, call it global, or an error; that's a side
issue). Key assumption: Python doesn't change its rules for what it
considers to be local.

That gives no way to get at (either read or write) yet another same-name
variable in a still-larger enclosing block, but _most_ CSNS schemes
don't; it doesn't come up often in practice, & a user can always worm
around it by renaming variables when it does happen.

This could go on (& on, & ...). I think you _could_ get a reasonable
CSNS scheme out of this, but I'm unclear on whether you want to. Tell
you what: I won't bring it up again unless you do <grin>.

> I still don't like the idea of making lambda "work right" (your words
> not mine :) without also fixing local defs. The restriction of lambda
> to a single expression will soon become a problem for fanatical
> lambda-lovers, who will then complain that as soon as they need to
> rewrite their lambda as a local 'def' the importation of variables
> from the surrounding scope stops working.

I said up front I thought my kludge was dead wrong if lambda got more
complicated, and what you say here is the flip side. The kludge is good
only if people accept that lambda != def, and never the twain shall meet.
What I did not say up front-- but would have had anyone asked <grin> --is
that I always thought the kludge was ugly.

> ...
> So to make lambda "work right" we need something that will also work
> for local defs (QED).

OK, I'll accept that as given (what the heck -- you won't give up on it,
& I'm secretly glad you won't <smile>).

> How about the following piece of lateral thinking: add default
> argument values, and evaluate the default values (once) in the
> defining scope.

My opinion? It's unbelievably clever! I saw David Copperfield make the
Statue of Liberty disappear once, and eventually figured out how he did
it. But _this_ is a _real_ trick <beam>:

> This solves a totally unrelated problem (*args is most often used to
> implement optional arguments) and can lead to relatively clean code
> using "idiom" like the following:
>
> def make_incrementor(incr):
> return lambda x, incr=incr: return x + incr
>
> or (without lambda):
>
> def make_incrementor(incr):
> def incrementor(x, incr=incr):
> return x + incr
> return incrementor

When you say "evaluate the default values (once)", I'm assuming that
means whenever the lambda expression itself or def statement itself is
evaluated (i.e., "def incrementor" is evaluated once per invocation of
make_incrementor, and the RHS of "incr=incr" would be evaluated at, and
only at, those times). If that's not what you meant, you meant to mean
that <wink>.

I believe Steve's original example could then be written:

def collect(seq, attrib):
return map(lambda obj, att=attrib: getattr(obj, att), seq)

and mine as:

def examine_property(self, prop):
...
damned = filter(lambda p, key=prop: p.has_key(key), self.people)
...

If that's right, I'd be very happy with it, for what it does for simple
lambdas, and for all its other uses (does seem to address many practical
issues at one stroke!). I'm sure it will take people some time to get
used to it, but I can't imagine that a cleaner or less-burdensome
approach is possible, short of going the whole (& much more involved)
general nested scoping route.

> ...
> (Note that no exportation is supported!)

Good! Write access is the hard part of CSNS in Python, and I doubt it
would be any easier in this context. Besides, "a local variable's
binding can be changed only by the function that owns the variable"
is a nice, simple rule.

in-a-world-with-too-few-of-those-ly y'rs - tim

Tim Peters tim@ksr.com
not speaking for Kendall Square Research Corp