Could Emacs be rewritten in Python?

Beni Cherniavsky cben at techunix.technion.ac.il
Fri Apr 11 09:43:00 EDT 2003


Christian Tanzer wrote on 2003-04-11:

> Carl Banks <imbosol-1049990205 at aerojockey.com> wrote:
>
> > > Maybe I'm missing something, but non-dynamically scoped globals just
> > > seem like a bad idea to me.
> >
Agreed.  If you have any globals at all that someone might ever want
to check, making them dynamically scoped is the right thing.  Simple
single-valued non-scoped globals are the true evil.

> > What you're missing is that Globals are Evil(tm), and furthermore,
> > that if your program depends on changing a global in a dynamic scope,
> > it badly needs to be redesigned. (To wit, that functions that refer
> > to the global you want to change need to be changed to accept it as an
> > argument.)
> >
> > I think dynamic scpoing is a wholly bad idea, and simplifying a very
> > misguided programming practice doesn't make it any less so.
>
That's a good idea, in theory :-).  In practice, the problem is that
you don't always know before-hand what will need parametrizing.  Can
you list down in your interface spec all the parameters your code
might depend on?  What if deep down it contains some sanity check that
can print an error message to stdout?  Or writes a log file to the
current directory?  Or launches another program to your job that
depends on some environment variable?  It's hard to eliminate all
these dependencies and passing them around is too insane; so you can
either make them hardcoded, modifiable global (almost equally evil) or
dynamic (managable)...  If you forgot to add these minor parameters to
your function's interface, you can't fix it in a compatible way,
except by dynamic scoping.  It allows you to "tunnel"  a parameter
through code that is unaware of it.  It lifts the burden of specially
handling it all the way up.  It sounds like ... exceptions!
Exceptions are dynamically scoped, and this solves *so many* issues.
It's the single most important idea of exceptions vs. traditional
error return technics.

So I argue that dynamic scoping done right, unlike simple globals, is
not always evil.  It's completely equivallent to passing all your
environment, except that you don't have to write that explicitly,
which can make all the difference.  Frequently, what you really want
is to parametrize a *proccess*, not just a specific call.

For example, in Unix, I/O redirection, the current working directory
and most other process parameters are dynamically scoped: it's
implemnented by copying from each process to its children but to you,
it's just magically inherited.  Actually the copying semantics are the
only right way to do dynamic scoping in the face of paralell
processes/threads - it's inherited but later it can be changed
independently.

The parametrize-a-whole-process idea is the most convenient way
invented to date to handle issues like I/O.  Unfortunately, most
languages don't have with-output-to and the like, so inside a each
proccess it works as a single-valued global, with all the
inconvenience.  The fix is obvious - the language should provide
dynamic scoping emulation to complete the illusion <wink>.

Any parameter that changes with infrequenlty, whose use is scattered
throughout the system and that is not interesting to other subsystems
is a good candidate for dynamic scoping.  Consider environmet
variables in Unix: they are probably the biggest evidence for dynamic
scoping working on large scales.  In fact, they work on much larger
scales than any other mechanism I can think of - they allow disperate
programs written independently to communicate, "tunnelling" through
other applications, and with quite good results!  Lexical scoping only
works inside a single program, as far as I can see...

> You are of course right. Surprisingly though, it works very well for
> Emacs. Passing arguments would *not* work in the context of Emacs.
>
That's what remains to be seen :-).  Probably not all aspects of Emacs
are best handled by dynamic scoping but some probably are.


I think that the most Python way to abstract dynamic scoping would be
to disconnect it from actual scoping, leaving only the dynamic binding
part.  "Special variables", like in CL and Scheme's fluid-let won't
fit well because in Python a value can be stored in so many ways - as
a module/class/instance attribute, as a local variable, as part of a
data structure...  So I think we need something analogous Java's
ThreadLocal objects - a single "magic" object that dispatches you to
the binding you should see.

Then (ignoring compatibility issues), the sys module would contain
three Dynamic attributes - std{in,out,err} and one would be able to
write:

with sys.stdout.bound_to(file('quux')):
  do_something_involving_printing_somewhere()

You get the idea :-).

> Practicality-beats-purity-ly yr's,

the-Right-Thing-always-has-negative-overhead-
(if-only-you-find-this-thing)-ly y'rs
  Beni Cherniavsky <cben at tx.technion.ac.il>





More information about the Python-list mailing list