Can Emacs Lisp Fix Its Namespace Problem by Copying JavaScript Practice?

By Xah Lee. Date:

the JavaScript lang, because it doesn't have name space and because the way it is used on the web, there arises a style where all js code try to minimize the number of exposed names. [see JavaScript Variable Scope: Function Level vs Block Level]

for example, in jQuery or any JavaScript lib, they only export one single name. (in jQuery, that's $ or jQuery. [see jQuery Tutorial by Example]) All the rest of vars or function names used by the lib is made to be properties of that single exported name.

this is interesting. In emacs lisp, it suffers the same problem of no namespace. However, the conventional solution is simply to attach a prefix to all names. e.g. suppose i have a lib called Xah Fly Keys. All var and function names in that lib will start with xah-.

but emacs lisp also supports function properties, or hash table, or list... the bottom line is that, it's also possible in elisp, to make it so that one package just export one single name.

i haven't looked further. Is this easy to do? anyone seen this idea done?


here's a excellent answer by [Yuri Khan].

You could say in Javascript each object is a namespace — the names of its properties are scoped in it and it alone (and objects for which it is a prototype). And the syntax to retrieve a member of a namespace is very light.

In Python, too, objects are namespaces: you can attach any kinds of properties to any object. A Python module is an object in the sense that it has address, so it can be the value of a variable. The Python syntax to access a member of an object is also very light.

In Emacs Lisp, every time you write (defun …), you define a global name. If you don't want to give a function a global name, you can make it a lambda. But then, to access it, you need to place it into some data structure. One that makes it possible to give local names. Maybe a hash:

(defconst my-module #s(hash-table data (
  'inc (lambda (x) (+ x 1))
  'dec (lambda (x) (- x 1))
  'add (lambda (x y) (+ x y)))))

You've created your module object, using just one global name (okay, you also polluted the global namespace with three symbols 'inc, 'dec and 'add, but that's ok because they are just symbols). Now you can access these functions:

((gethash 'inc my-module) 1) ; ⇒ 2

((gethash 'add my-module) 42 15) ; ⇒ 57

Why hasn't this convention taken off in Lisp? Because it's ugly. In Javascript, Python, Pascal, Haskell, when you want a member of a namespace, you write: namespace_name.member_name. Notice also that namespaces may be nested: x.y.z. In the above model, the equivalent syntax would be: (gethash 'z (gethash 'y x)).

Okay, what if modules are not hashes but high-order selector functions:

(defun my-module (member)
  (pcase member
    ('inc (lambda (x) (+ x 1)))
    ('dec (lambda (x) (- x 1)))
    ('add (lambda (x y) (+ x y)))))

((my-module 'add) 24 38) ; ⇒ 62

You can nest modules if you really want to and the syntax for accessing a member of a nested module is then: ((x 'y) 'z) where x is the top level module object, 'y is the submodule selector symbol, and 'z is the nested member selector. But you can't really use all benefits of nested modules because you have to declare the whole top-level module in a single source file.

You can locally import members from such a module:

(let ((inc (my-module 'inc)))
  (inc 1)) ; ⇒ 2

You can give local aliases to modules:

(let ((m my-module))
  ((m 'inc) 1)) ; ⇒ 2

This convention could work in principle. But you'd have to first convince everybody that it is superior to the prefix convention. After all, it requires 4 keystrokes per member access, while prefix requires 1. And you'd have to teach all of the hook and keybinding mechanisms in Emacs to deal with unnamed functions nicely. (Currently, if you hook an anonymous function, you cannot then unhook it.) Or maybe you'd have to invent a different syntax for a module, where members are not constructed on the fly but are local variables with persistent addresses.