Could Emacs be rewritten in Python?

Alexander Schmolck a.schmolck at gmx.net
Sun Apr 13 18:58:48 EDT 2003


Carl Banks <imbosol-1050078176 at aerojockey.com> writes:

First of all, I'd better clear up some potential misunderstanding: I *do not*
of course advocate that lexical scoping in python (or anywhere else, for the
matter) be ditched for dynamic scoping. If that was what you thought I was
arguing, I can't blame you for not taking it seriously and I think I should
have been clearer (at least in the last paragraph of my second post).

What I *am* claiming is that dynamic scope -- and not global scope in the form
currently implemented in python -- is the right thing to maintain implictly
shared state (cf. Common Lisp where global variables are either dynamically
scoped or constant whereas everything else is statically scoped, unless
explicitly declared otherwise -- which seems the right idea to me).

To avoid further confusion, I'll use global scope to refer to the module level
scope that is currently available in python and lexical and dynamic scope
according to their normal definitions and as one finds them in CL (and the
former also in python).



> Alexander Schmolck wrote:
> > Carl Banks <imbosol-1049990205 at aerojockey.com> writes:
> >
> > You did notice, of course, that you don't only need to change that particular
> > function foo, but also everything (directly or indirectly) calling foo? As
> > well as everything that is called (directly or indirectly) by foo and that
> > uses this global state information? Including 3rd party code and builtin
> > constructs of the language?
> 
> Yes.  Since the idea here is to rewrite the Emacs in Python, you have
> to rewrite all of this anyways.

I'm simply interested in the question as to whether globals of the type C,
Java and most languages, but specifically python, have them are a good idea or
whether dynamically scoped variables are superior. So I'd prefer not get too
sidetracked by Emacs and its uses of dynamic scope (some bad, some good, IMO).
The above describes by no means a problem limited to refactoring code in
dynamically scoped legacy languages but anyway, since you bring it up: there
is rewriting and rewriting -- not that anyone who's got the necessary
ressources would be stupid enough to rewrite emacs anyway[1] -- I'd personally
rather rewrite leveraging more rather than fewer powerful abstractions.


> 
> 
> >> I think dynamic scpoing is a wholly bad idea, and simplifying a very
> >> misguided programming practice doesn't make it any less so.
> > 
> > How much time did you actually spend thinking about global variables and
> > dynamic scope or what I wrote before you posted?
> > 
> > Why are global variables evil?
> [snip reasons globals are evil]
> 
> I didn't say globals are evil. I said Globals are Evil(tm). Big difference.
> (You should learn the meaning of (tm); it means the writer fully realizes
> that it's only a general truth, even though others consider it an absolute
> truth.)

I can't see were I attribute the claim that "globals are evil" to you -- *I*
happen to think globals of the broken kind python suffers from are evil (plain
and simple, no (tm)) and dynamic scope would provide a much better solution.
I'm always willing to hear why I'm wrong.

> I do not oppose global variables in general.

That was never in doubt. The question is not so much whether or not one should
have implicitly shared variables (in python and similar languages), but how
they should work and how they should be used. Your answer to my question on
your opinion on why python provides global variables seems to be (correct me
if I'm wrong):

I)  to provide *one*[2] implicitly shared state that should only be altered in
    an irrecoverable fashion.

My answer would be:

II) to provide a poor substitute for implicitly shared state that can be
    shared at different granularities and so that the same name can
    simultanously be exposed with different values to different values to
    different parts of the program -- all with automatic stack-popping style
    recovery of former values on natural or unnatural block exit.

 
> I do oppose global variables where there are situations where it feels
> necessary to change it and restore it.  That tells you right away that
> your functions should not use a global, but should have it passed in.
> Designing such a function to refer to the global anyways is Bad
> Programming(tm).

Repetition doesn't make this claim doesn't make it more or less true. Why not
instead back it up in some way or attack a provided example where I feel that
you *do* want to modify and restore state?

You say:

> These issues should be handled by global variables if they indeed are
> global in nature.  The stuff you mentioned usually is.

and then:

> I have not said lexical scoping handles the issues you have referred
> to better than dynamic scoping.  I have said that the issues you refer
> are only issues in the presense of Bad Programming(tm).  Anyone using
> globals discriminately will not have such issues to deal with.

I infer this to mean that it's OK to have logging and to use global state to
control logging, as long as I don't want one part of the program to be treated
differently. So to come back to an example from my previous post, a
particularly critical routine that should be logged at a higher level without
affecting the rest of the logging operations, would be Bad Programming(tm)?
Same for output precision, assertions and other debugging options (or
localized fine-tuning of e.g. floating point behavior or error handling etc.)?

Would you mind elaborating a bit? I do not yet fully appreciate why you'd
always want to share state either in a fully parameterized fashion or with
zero granularity and no shadowing or why my examples epitomize Bad and
indiscriminate Programming(tm).

> I have not said lexical scoping handles the issues you have referred
> to better than dynamic scoping.  I have said that the issues you refer
> are only issues in the presense of Bad Programming(tm).  Anyone using
> globals discriminately will not have such issues to deal with.

A bold claim. I bet a few people in the Lisp community would disagree that
their use of dynamic variables reflects their limited coding and design
abilities.

Do you ever use try-finally?

> 
> But to answer your question: yes, dyanmic scoping is so awful it
> doesn't justify this particular benefit, especially when the benefit
> only arises in Bad Programming(tm).

Indeed, wickedness should be its own reward -- if only we could agree that Bad
Programmers(tm) are the sole beneficiaries.

> In fact, dynamic scoping is so awful is doesn't justify any benefits.

Have you had traumatic childhood experiences with early perl or lisp dialects?
:)
 
> It's not just me; meny, many people regard dynamic scoping as a bad
> mistake.

[As explained, lexical scope as default for local variables is not questioned]

Well many, many people regard C as the ulitmate programming language and I
think those insightful individuals also have every right to regard dynamic
scope as an aberration, for I indeed C, to my knowledge, is almost utterly
devoid of anything resembling it (as long as you don't happen to shun any
posix pollutions like forking etc.).

Nonetheless as quite a few smart people also regard non-dynamically scoped
globals as a bad mistake, so I'd prefer to to see further support apart from
these arguments from authority (your's and the anonymous masses').

Also note that, as pointed out in Beni Cherniavsky's informative posting,
python already shows various signs of dynamic infiltration such as exceptions.

[I assume the following was written under the impression that I advocated
global scope for all variables, but I'll reply anyway just in case]
 
> I don't wish to go into detail here.  The main problems are: It forces
> you to use defensive naming schemes, even for your local variables.

Not if you have lexical variables as default. I guess you could even simply
adapt the existing scheme (where you have to declare globals explicitly to be
able to set them) for dynamic scope. Thus (for illustrative purposes):

def bar():
  global foo      # shares state, modifies last version of foo in according to
                  # call stack;
  global quux = 3 # shadows quux (or introduces a new dynamically scoped
                  # variable, but only visible to callees)

  my_var = 3      # no declaration => lexically scoped (no need to look beyond
                  # this block)

> You cannot determine the variables in effect just by looking at a function
> in context. You cannot do lexical closures. It's less efficient.

All equally true of globals as they are in python. BTW, not that it matters,
but dynamically scoped variables may well be more efficient than passing
parameters (the reason that it doesn't matter is of course that such design
decisions shouldn't be influenced by minor performance characteristics).

> 
> > Rather you
> > just pretended the issue didn't exist and I was just being stupid
> > for not realizing this to start with.
> 
> Don't be presumptuous.

I'm trying.

'as


Footnotes: 
[1]  That is not to say that writing a *different* and (noticeably) *better*,
     emacs-inspired editor wouldn't be a worthwhile undertaking.

[2]  Although with (arguably) different visiblility.





More information about the Python-list mailing list