help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Emulating namespaces


From: Pascal J. Bourguignon
Subject: Re: Emulating namespaces
Date: Wed, 08 Dec 2010 15:11:23 -0000
User-agent: Gnus/5.101 (Gnus v5.10.10) Emacs/23.1 (gnu/linux)

LanX <lanx.perl@googlemail.com> writes:
> I was meditating about how namespaces are realized in perl and now I'm
> wondering if this behaviour could be mimicked in elisp.

Actually, emacs has already the primitive mechanism needed to
implement packages.  This can AFAIK be done entirely in emacs lisp.

If only it had reader macros, we could provide the pack::sym and
pack:sym syntax too (and correct the :keyword syntax).



Emacs lisp stores symbols in obarrays.  The variable obarray is used
by intern, mapatom, etc.



So, basically:

(defvar *package-name-map* (make-hash-table :test (function equal)))

(defvar *list-all-packages* '())
(defun list-all-packages () (copy-list *list-all-packages*))


(defstruct (package (:constructor %make-package)) 
   name
   nicknames
   use-list
   used-by-list
   shadowing-symbols
   %obarray)

(defun* make-package (name &key nicknames uses size)
  (assert (notany (function find-package) (cons name nicknames)) 
          (name nicknames)
          "There is already a package with the same name or nickname")
  (let ((p (%make-package :name name
                          :nicknames nicknames
                          :use-list (or uses (find-package "EMACS-LISP"))
                          :%obarray (make-vector size nil))))
     (push p *list-all-packages*)
     (dolist (name (cons name nicknames))
         (setf (gethash name *package-name-map*) p))
     (internalize-used-symbols p)
     p))


;; bootstrap the emacs-lisp package:

(defvar *package* (let ((p (%make-package :name "EMACS-LISP"
                                          :nicknames '("ELISP")
                                          :use-list '()
                                          :%obarray obarray)))
                       (push p *list-all-packages*)
                       (dolist (name '("EMACS-LISP" "ELISP"))
                           (setf (gethash name *package-name-map*) p))
                       p))

(defmacro in-package (package-designator)
   `(progn
       (setf *package* (find-package ,package-designator))
       (setf obarray   (package-%obarray *package*))
       *package*))


So, if you take care to always :use "EMACS-LISP" to always have access
to in-package, you can skip from one obarray to another for further
reading, because without modifying the reader, you cannot use

   (elisp:in-package :elisp)

to come back.


You will need wrappers to map packages to obarray for function such
as intern.


Also, we could just use emacs-cl...
-- 
__Pascal Bourguignon__                     http://www.informatimago.com/


reply via email to

[Prev in Thread] Current Thread [Next in Thread]