Could Emacs be rewritten in Python?

Beni Cherniavsky cben at techunix.technion.ac.il
Fri Apr 18 00:12:41 CEST 2003


In comp.lang.python, you wrote:
>Robin Munn wrote:
>> Paul Foley <see at below.invalid> wrote:
>>>
>>>What if another thread (B) does the same thing, and changes sys.stdout
>>>while this thread (A) is still inside the "try" block?  And if thread
>>>A runs its "finally" clause and resets sys.stdout while thread B is
>>>still in its "try" block, they screw each other.
>> 
>> This is the classic problem that arises when two threads need to use any
>> shared resource, isn't it? 
>
>No, actually it's the classic problem that arises when
>two threads spuriously share something (a global variable)
>that shouldn't have been shared in the first place.
>
True.  Blocking here on locks is completely unnecessary.

>This is *not* an argument for dynamic scoping. It's an
>argument for explicitly passing things the state that
>they need!
>
No, this is just an argument for *passing* things the state that they need.
Whether it is done explicitly or implicitly is quite irrelevant to the obvious
requirement that things should work accross threads.  It's still an
interesting question, or we wouldn't write so much <wink> but it doesn't
follow directly.

Of course, currently Python allows to fulfil this only by passing things
explicitly.  So there is no choice.  But there could be.

I still don't see why is dynamic binding inherently buggy.  I'm talking about
dynamic binding done right, so that a new thread gets a copy of all dynamic
variables from the parent thread; afterwards both threads can alter them
independently.  (This sounds like a very uneffecient implementation; it can be
optimized in various ways to copy only those variables that are needed).

Note that the semantics is perfectly correct - every called function gets all
dynamic variables as implicit parameters, just like you would get with
explicit parameters.  The only difference is whether you have to spell this
out in your code.  So the question is just: which leads to less programmer
mistakes?

Truly, some confusion can result when one controls the same thing both with a
dynamicaly bound implicit parameter and an explicit parameter and when you
don't know which parameter is controlled in which way.  However, it is easy to
use it cleanly.  If you decide once that rebinding sys.stdout is the *right*
way to pass an output parameter, and use this consistently in your program,
there is nothing evil to it!  These two approaches are completely equivallent:

def foo():
    bar()
    with output to file("f2"): baz()   # neutrally bogus syntax :-)
    
def foo(f1):
    bar(f1)
    baz(file("f2"))

If inheriting the parameter (like in the `bar` call) is the typical situation,
the dynamic approach seems better; if overriding it (like in the `baz` call)
is mroe typical, explicit passing seems better.  The main criteria for
deciding on each parameter how it should be passed are:

- Whether you work with only one value of it most of the time.
- Whether one wants it by default to be inherited by called functions.

For output, the answers are usually yes, so UNIX's designers decided it should
be passed implicitly - and got it right IMHO, at least at the process level. 
Perhaps inside a single program the balance is different but I think the
implicit passing would be nice inside a program too.

-- 
Beni Cherniavsky <cben at tx.technion.ac.il>





More information about the Python-list mailing list