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