Could Emacs be rewritten in Python?

Kim Petersen kp at kyborg.dk
Wed Apr 9 18:06:00 CEST 2003


Alexander Schmolck wrote:
> Kim Petersen <kp at kyborg.dk> writes:
> 
> 
>>Alexander Schmolck wrote:
>>
>>>Kim Petersen <kp at kyborg.dk> writes:
>>
>> >> (snip)
>>
>>>>function in elisp - do a shallow copy of local variable space (dictionary) and
>>>>send it as the local vars - you can safely throw away the dict after function
>>>>returns).
>>>
>>>Ahem, there are several thousand variables kicking about in global in emacs,
>>>you want to copy them all for each function call?
>>
>>look above - *Local* variable space ... globals stay globals.
> 
> 
> Maybe we have a misunderstanding. 
> 
> I thought in your scheme every call to a lisp function foo (from python *or*
> another lisp function) is to be implemented by making a copy of the locals and
> passing it to foo and this copy is discarded after return. If so, this won't
> work (because foo can mess with its callers *locals*; also globals *don't*
> stay globals -- a let binding of a global name means it can no longer be
> globally modified further up the call tree).

No misunderstanding... and possibly not efficient - thats why i said 
that you could do push/pop of bindings instead... since then i 
remembered that elisp (or any other lisp for that matter *doesn't* have 
global variables - so it would be inefficient). But to make it efficient 
and usable you can do it with a class instead (that simulates a dictionary):

class Borg: pass

class LispNameSpace:
    def __init__(self):
       self.nstack=[]
       self.vars={}
       self.undefined=Borg()
    def getcontext(self): return len(self.nstack)
    def restorecontext(self,n):
       for i in xrange(len(self.nstack),n,-1):
          if self.nstack[i][1]==self.undefined:
             del self.vars[self.nstack[i][0]]
          else:
             self.vars[self.nstack[i][0]]=self.nstack[i][1]
    def localvar(self,name,value=Null):
       if self.vars.has_key(name):
          self.nstack.append((name,self.vars[name]))
       else:
          self.nstack.append((name,self.undefined))
      self.vars[name]=value

only thing missing now - is overwriting __getitem__,__setitem__ to do 
lookup and set of variables - possibly on failure to find a name in 
namespace default down to python namespace - making it really usefull.

implementation of let:

def let(cons,namespace):
    # of course a scheme to reasonably map lisp functions to python
    # implementations is needed - i just assume that (f x y z) is called
    # here as f(lisplist(x,y,z),namespace)
    #
    context=namespace.getcontext()
    defs=cons.car()
    body=cons.cdr()
    if iscons(defs.car()):
       namespace.localvar(defs.car().car(),defs.car().cdr().car())
    else:
       namespace.localvar(defs.car())
    lispeval(body,namespace)

> 
> A better example to clarify:
> 
> (defun foo()
>   (message "when foo is called folding is: %s" case-fold-search)
>   (setq case-fold-search :evil))
> (defun bar()
>   (message "when bar is called folding is: %s" case-fold-search)
>   (let ((case-fold-search t))
>     (foo)
>     (message "what did foo do to folding? %s!" case-fold-search))
>   (message "bar's last folding is: %s again" case-fold-search))
> (defun quux()
>   (message "before bar:%s" case-fold-search)
>   (bar)
>   (message "after bar:%s" case-fold-search))
> (quux)
> 

and all this would be handled gracefully.

> 
> before bar:nil
> when bar is called folding is: nil
> when foo is called folding is: t
> what did foo do to folding? :evil! ;; !!!
> bar's last folding is: t again 
> after bar:nil
> 
> Tell me if you think this would work, too and I'll just reread your message.

Yep it will - and no need to look back - i think i clarified?

> 
> 
> 'as






More information about the Python-list mailing list