Python's Lisp heritage
Christopher Browne
cbbrowne at acm.org
Wed Apr 24 00:14:50 EDT 2002
Centuries ago, Nostradamus foresaw when Tim Peters <tim.one at comcast.net> would write:
> [James J. Besemer]
>> ...
>> The original semantics (as formally defined in Lisp itself
>> [McCarthy]) called for dynamic binding.
>
> It seems this would have been a surprise to McCarthy <wink>:
>
> http://www-formal.stanford.edu/jmc/history/lisp/node4.html
>
> See paragraph "d. Free variables". When a user bumped into a function where
> the difference between dynamic and lexical scoping mattered, and lexical
> scoping was what they needed, "I must confess that I regarded this
> difficulty as just a bug". The understanding of these issues was much
> muddier at the time.
>
>> ...
>> I find it highly ironic that Perl originally did it the wrong way
>> ("local"), although later they introduced a now-recommended static
>> binding ("my").
>
> More recently, REBOL went down the same path. Dynamic scoping is attractive
> for implementation reasons; everyone who succumbs eventually regrets it
> (except for RMS in elisp ...).
Dynamic scope buys you the ability to not need to specify _all_ the
values that you might be customizing.
If a new Emacs mode requires adding in a bunch of additional
parameters, dynamic scope lets them be visible throughout the scope
during which they are "live" as opposed to just within the environment
in which they were defined.
>From a paper on Emacs:
"Some language designers believe that dynamic binding should be
avoided, and explicit argument passing should be used
instead. Imagine that function A binds the variable FOO, and calls
the function B, which calls the function C, and C uses the value of
FOO. Supposedly A should pass the value as an argument to B, which
should pass it as an argument to C.
This cannot be done in an extensible system, however, because the
author of the system cannot know what all the parameters will
be. Imagine that the functions A and C are part of a user extension,
while B is part of the standard system. The variable FOO does not
exist in the standard system; it is part of the extension. To use
explicit argument passing would require adding a new argument to B,
which means rewriting B and everything that calls B. In the most
common case, B is the editor command dispatcher loop, which is
called from an awful number of places.
What's worse, C must also be passed an additional argument. B
doesn't refer to C by name (C did not exist when B was written). It
probably finds a pointer to C in the command dispatch table. This
means that the same call which sometimes calls C might equally well
call any editor command definition. So all the editing commands must
be rewritten to accept and ignore the additional argument. By now,
none of the original system is left!"
If all you have is lexical scoping, parameters have to get explicitly
passed down the chain in order to get from function A to function C.
That means introducing additional parameters to function B, which
didn't actually care about those extra values.
Most of the time, lexical scope is likely to be more useful. But
there are places where dynamic scope is to be preferred.
--
(concatenate 'string "cbbrowne" "@cbbrowne.com")
http://www.cbbrowne.com/info/spreadsheets.html
How does the guy who drives the snowplow get to work in the mornings?
More information about the Python-list
mailing list