Could Emacs be rewritten in Python?

Carl Banks imbosol-1050288268 at aerojockey.com
Mon Apr 14 07:52:31 CEST 2003


Alexander Schmolck wrote:
> Carl Banks <imbosol-1050078176 at aerojockey.com> writes:
>> 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.

Ok, let's leave Emacs out of this.


>> >> 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.

Let's leave Python (and C and Java) globals out of this.


>> 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?

I didn't think I needed to back it up nor attack an example.  We all
know Globals are Evil(tm), and passing a parameter into a function
with a global is therefore Bad Programming(tm).  This *is* usually
true.

It thought it was obvious.

But see below.


> 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.)?

Ok, let me back off a bit.  That you might want to change a program's
state in a dynamic scope is reasonable.

Typically, however, that kind of thing should be handled by passing
objects around as arguments.  For example, consider the use of current
buffer in Emacs.  (We are still leaving Emacs issues out of it; I'm
just using it as an example of bad programming.)  Most functions in
Emacs operate on the current buffer, a piece of global state.  In
order to operate on a non-current buffer, you have to temporarily
change the current buffer.  That is bad programming; functions should
take the buffer to operate on as an argument.  Some people might whine
that the absense of dynamic scope would make life difficult, but, in
fact, it is their own incompetence and/or laziness that makes life
difficult.

However, as you say, there are certain side concerns, like logging,
where it is at best inconvenient, and at worst counterproductive, to
pass a value around as an argument, so it gets made a global.  It's
very common to do this, of course.

However, I think changing a global value within a dynamic scope, in
situations where it wouldn't be better to pass around an argument, is
a very uncommon concern.  And frankly, I think it's too much of a
special case to introduce a confusing and separate scoping rule that
has all kinds of nasty and big-ridden problems.

So if you need that kind of thing, please don't destroy the language
by adding dynamic scoping.  Just live with a try ... finally.

Or get off your lazy ass and refactor your code like you should.


>> 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.

Retracted.


> Do you ever use try-finally?
 
Yes, but not to change any program-visible globals.

(Yes, I know open affects process file decriptor tables, but all my
code sees is a file object which is a local variable, that I pass as
an argument to any function I call.  Almost everything I use try
... finally for is stuff that the OS forces to be part of the
process's global state.)


>> 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?  :)

Yes


[snip stuff about many people agreeing with me and it doesn't mean anything]
> Also note that, as pointed out in Beni Cherniavsky's informative
> posting, python already shows various signs of dynamic infiltration
> such as exceptions.

I don't think exceptions matter one bloody bit when it comes to
scoping issues.


> [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.

Ok.  Let's not forget that, lexical locals or not, this is still a
problem for dynamic globals.

With all globals in dynamic scope, software packages that declare
globals must take steps to avoid name clashes.  Or, you can make a
pitiful attempt to work around this such as the absolutely horrid
abomination known as the Lisp Package system.


>> 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).

The first is kind of true in Python; but not generally true of
lexically-scoped variables.  Even in Python, when you see a global,
you know at least what module it belongs to.  When you see
dynamically-scoped variable, you can't tell what it is or who set it.
Python, as it is, is still much better in this regard.



Closing remarks:

You seem to acknowledge the existence of the well-known problems with
dynamic scoping (because you agree lexical scoping is better for
locals).  But, you seem to have ignored the fact that these problems
don't go away just because the variable in question is global.  You
say globals should be dynamically scoped because they can do this
neat, funky trick, but never consider the excess baggage the dynamic
scoping brings.

Making all globals dynamically scoped is a mistake because of the
problems dynamic scoping causes, which, I say, are far more severe
than the slight inconvenience of having to explicitly save and restore
a value in the few special cases where that would be useful (and not
bad programming).

I say dynamic scoping shouldn't be in the language, period, because,
despite your good intentions, someone will put it to evil use.  Ok,
you can say that about any language feature, but this is an evil I
cannot bear.  Having such a dispicable wart in the language is simply
not worth saving you the inconvenience of using a try ... finally to
change your log level.


-- 
CARL BANKS




More information about the Python-list mailing list