Re: Lambda binding solved?

Tim Peters (tim@ksr.com)
Sun, 06 Mar 94 17:21:00 EST

> > [tim, griping that he can't follow the mechanism discussions without
> > reference to the problems they're intended to solve]

> [steve, noting that we did start by trying to get 'collect()' to work]

Right! I had no problem there. It's when the discussion branched into
tree-structured dictionaries, bind/merge, a new module statement,
PostScript scoping, ... that I got irretrievably lost. I.e., it wasn't
at all clear that any of those yielded a usable solution to collect's
(lambda) problem, nor was it clear what problem they _were_ intended to
solve. I'm just trying to get the focus back, to problems instead of
putative solutions.

> ... one clean and simple solution, would be just to get rid of lambda -
> since it is unnecessary, limited and error prone. ( But since I LIKE
> lispish features like lambda,map,etc., I was not inclined to propose
> that solution until YOU brought it up. ...

We're in the same boat, Steve! If lambda can't be "fixed", it probably
_should_ be thrown out, but I'd much rather fix it if possible. Guido
already said that "the desire for importation of variables from outer
scopes into nested functions [is justifiable]", so I don't think the
attempt is futile, and indeed he suggested a clever way to do it.

I'm not clear on whether you think his proposal is "good enough", though.
Scoping reaches to the heart of a language design, so if you have other
problems with Python's scope rules I really want to know what they are
(else there's no way to judge the solutions).

> ... considering your comments about the mistakes everyone usually makes
> until they read and understand the reference manual chapter on scoping,
> and question 4.5 of the FAQ, there may be grounds for arguing that
> python's scoping rules ALSO create as many problems as they solve.

I distinguish strongly between one-shot ("learning") problems, and
continuing problems. The fact that Python functions and classes
textually nest, but scope doesn't, is confusing at first because it's so
very _unusual_. Once I grasped the Python rules, I never had a problem
with them again (until lambda <wink>).

But I don't know whether my experience is universal. How does it compare
with yours, or Jaap's, Jack's, Bill's, Mark's, [insert other names at
will]? Silence is always risky to interpret, but that so few old-timers
have spoken up about scope _suggests_ they don't have continuing problems
either (else I'd expect them to leap at a chance to change the rules!).

> One of the reasons that Static Scoping is considered a Good Thing,
> is that it increases the capability to understand code from local
> textual information and requires less global information. This
> was what I meant when I said that Python's scoping, in that case,
> didn't *LOOK* as if it was static.

I should have asked you about this before: I don't understand what you
mean here. If a Python function doesn't contain an instance of exec, or
the "*" form of import (and 99+% of functions don't contain either), its
local variables are exactly known at compile-time, and with reference
solely to the body of the function (you can't get much more static, or
local, than that!). E.g., in

def g():
f(i)
i = 2

"i" is local to "g", period. The context it's evaluated in makes no
difference:

i = 12
def f(n): return n
def g():
f(i)
i = 2
g()

If you run that, you get an "undefined _local_ variable" error on line 4
(the "f(i)" call). "i" is local because it's assigned to _somewhere_ in
g's body (a static determination made by looking at f's body in
isolation); there's nothing dynamic about it (and in particular it's not
the case that i "becomes local" after the assignment is _executed_: "i"
was unalterably and purely local at the time "def g" got compiled).

> Of course, it *IS* static scoping, but in that case, the result is an
> instance where one has to understand that what looks like a local
> expression is actually evaluated in a quite different context from the
> one in which it appears. The mechanics are quite different, but
> otherwise, that's just the sort of non-local effect that static scoping
> was supposed to avoid!

I need an example. I'm misunderstanding your point, or maybe not
understanding it at all. An example could clear that up, though!

> ... IF you understand the scoping rules and the way expressions are
> evaluated, dynamic scoping can be understood. You just have to remember
> that expressions may not mean LITERALLY what they APPEAR to mean - you
> have to consider the context in which they will be evaluated ... which
> seems to be pretty much what you're telling me about Python's static
> scoping.

No, what I'm telling you is that, in Python today, you must _not_ look at
the context in which they're evaluated! If you look at a Python function
(still ignoring exec and "*" imports) in total isolation, what's local
and what's global is 100% clear. It's only when you believe that the
context has something to do with it that you can get confused (and thanks
to Pascal etc, most everyone coming to Python is likely to have that
confusion at first -- it takes a while to grasp how _simple_ Python's
scoping really is <0.9 grin>!).

> ...
> But the point is that you have to stop and analyze it, you can't just
> read the code and expect that the "n" on line 7 has the same value as
> the "n" on line 6.

You can in Python! If line 6 and line 7 (or line 2 and line 5,349) are
in the same function, both instances of "n" are local to the function, or
both are module-global (modulo pathological exec and "*" import abuse).

> ... But INTERCAL was also the language that improved on the GOTO by
> introducing the COME-FROM statement.

and-computer-science-has-been-going-downhill-ever-since<snort>-ly y'rs
- tim