emacs-devel
[Top][All Lists]
Advanced

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

Re: Emacs Lisp's future


From: Tom Tromey
Subject: Re: Emacs Lisp's future
Date: Thu, 13 Oct 2016 15:35:17 -0600
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/25.1.50 (gnu/linux)

RMS> It would take a lot of work for me to try to find the code
RMS> by looking at that directory, and then a lot more work for me
RMS> to figure out what the package does by reading the code.

RMS> Would you please post the documentation here?

I've appended it.

I can send the source if you want as well.  It's short (388 LOC
including comments).  The essence of it is hooking
internal-macroexpand-for-load to rewrite forms.

Tom

This is a simple module system for Emacs Lisp, inspired by [Nic
Ferrier's 
proposal](https://lists.gnu.org/archive/html/emacs-devel/2013-07/msg00738.html).
  It allows short symbol
names in the source code but exports the names using the standard
elisp-style module prefixes.

To define a module, see `define-module`.  After a `define-module`,
some symbols in the current load file will be renamed.  In
particular, symbols coming from `defvar`, `defconst`, `defun` and
the like will be renamed -- but other symbols will not be.  This
feature is critical to keeping normal Elisp working, as the Emacs
core sometimes requires certain symbol names in APIs.

Note that a private symbol must be seen -- declared with `defvar` or
the like -- before any uses.  Otherwise the renamer will not know to
rename the use.  Normally this is not a problem but you must take care
to declare internal functions when you need mutual recursion.  You can
do this like so:

```elisp
(declare-internal-function private-function)
```

When renaming, exported symbols will be given the package prefix, and
internal symbols will use the "--" convention.

E.g., consider:

```elisp
(define-module testmodule :export (somevar))
(defvar somevar nil)
(defvar private nil)
(provide 'testmodule)
```

This defines a module named `testmodule` and two variables, an
"exported" one named `testmodule-somevar`, and a "private" one named
`testmodule--private`.

Symbols from other modules can be imported using `import-module`.
Because module boundaries are purely based on symbol naming
conventions, you can also "import" from modules that do not use
module.el.  These modules are called "implicit" modules.  Importing a
module also `require`s the feature.

```elisp
(define-module testmodule)
;; Import some symbols from M.
(import-module M :symbols (a b c))
```

Sometimes, for an implicit module, the name of the feature and the
name of the module prefix differ.  In this case you can use the
`:prefix` keyword:

```elisp
(import-module cl-macs :prefix cl)
```

A module is closed by calling `provide`.

This module system doesn't have an explicit notion of submodules.
Rather, it piggy-backs on the existing feature of `require`, that lets
a directory separator in the symbol name load a file from a
subdirectory:

```elisp
(require 'feature/subfeature)
```

### Caveats

The renaming is not perfect.  If your code uses `intern` or otherwise
reflects on symbols then you have to be aware of the transforms done
by module.el.

Another issue is that autoload cookies aren't rewritten.  This seems
reasonably hard to fix, since they can refer to any symbol and so the
cookie extraction code would have to duplicate the importing logic.



reply via email to

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