reddit / emacs
Emacs Lisp shorthands as namespacing system
geospeck · 2022-11-27 09:48
yantar92 · 2022-11-27 10:31
Re: versioning. Note that `provide` allows to define "subfeatures", which might be an alternative to the proposed versioning via shorthands.
ayy_ess · 2022-11-27 11:39
How would advising functions or variables/state work with versioned namespaces? It sounds useful for individual packages to know their dependant functions and variables will exist but it sounds tricky from the user's side who might want to change behaviour in every version.
yantar92 · 2022-11-27 12:04
Good point. Adding to it, using `cl-letf` around function calls may also become impossible.
arthurno1 · 2022-11-27 12:37
In which way can we use subfeatures in that way? I am asking genuinely, I don't understand what you mean here, but would be glad to hear if you can explain.
In my opinion, the only downside with renaming thing is that we have to use annotations in form of code comments, instead of some proper lisp call (or am I just ignorant here?), and that it does not auto-understands prefixes defined in defgroups for customize, so we could just (require 'package as 'new-name), Similar as it works in Python for example. Or maybe it works so? I really haven't used it yet, but need it for a HTML generator thing, and am thinking of renaming things in a macro on the fly, but would really prefer to use built-in automatic stuff.
yantar92 · 2022-11-27 12:45
> In which way can we use subfeatures in that way? I am asking genuinely, I don't understand what you mean here, but would be glad to hear if you can explain.
Normally, Emacs does not load the already loaded feature when using `require`. However, if the required package defined subfeature unique to each version, one can `require` that unique subfeature thus loading the correct version of a package.
It will not work out of the box though as obarrays are shared regardless of subfeatures or even shorthands. So, we still need proper namespacing to make multiple package versions work in parallel. And, as mentioned in another comment, it is unclear what to do with advice system and, more generally, re-assigning function slots of symbols.
I don't fully understand the second part of your comment.
arthurno1 · 2022-11-27 12:58
Thanks for the clarification, I get it now.
For the second part, I meant that I dislike to type in renaming in comments for the local variables. Like shown in the blog:
;; Local Variables:
;; read-symbol-shorthands: (("snu-" . "some-nice-string-utils-"))
;; End:
I would prefer if I could type:
(require 'snu as 'some-nice-string-utils)
and Emacs would properly see ':prefix' in 'defgroup' definition in snu.el and rename prefix to the name defined after 'as'. Python can do: import package as some-other-name, and JS has similar import as name from "some-package".
But that is rather a minor.
yantar92 · 2022-11-27 13:13
I am not sure, but you might actually implement this kind of thing using reader macros. I recommend reading backquote.el for the details.
arthurno1 · 2022-11-27 14:08
Probably, I am not so familiar with reader macros in Emacs; I always thought Emacs does not have them :). But thanks for the tip, I'll take a look.
Anyway, I can do it in several ways; currently I parse html-spec, and generate functions for each element into an obarray, but I think I'll switch to generate code to a file instead, and use rewriting rules. That seams to be the least work, if I wish to freely mix Emacs lisp with html sexps. If I don't allow for using Emacs lisp in HTML, then I can just read the list one element at the time and emit the html/xml myself, but I would like to be able to mix in ordinary lisp, so it is a bit more involved. It is in a case like this where namespaces are handy. Both HTML and Emacs lisp define 'map', 'kbd' and 'input' for instance, and these are rather important functions in Emacs. Also, having global names like 'a' or 'p' is not a very nice idea either.
github-alphapapa · 2022-11-27 16:55
Really nice article. Thanks to Andrey for exploring the topic so thoroughly.
One minor note: Andrey wrote, "Later on same message, [RMS] mentions that Clojure is not a Lisp, but we will not go there." Actually RMS said, "Clojure is not Lisp," and the distinction is important, because while both use sexp syntax, Clojure is very different from Lisp internally. In other words, Lisp is more than just sexp syntax, and Clojure wasn't intended to be like Lisp internally.
flyin1501 · 2022-11-27 17:50
- "Clojure is not Lisp" = not "Lisp", as in a specific vision that is shared by a particular subset of Lisp family languages, including Elisp and Common Lisp
- "Clojure is not a Lisp" = does not belong in the general Lisp family of languages. Requires a controversial, exclusionary definition of what counts as a Lisp family language.
One is attacking Clojure but the other isn't. Misunderstanding which one is meant is a recipe for disastrous arguments. Clojure is a Lisp but it is not *Lisp*.
Language is annoying sometimes.
"Lisp" can mean:
- a specific language in the Lisp family depending on context,
- or a vision of how some particular languages can develop, particularly Emacs Lisp,
- or a language family, which often has some fuzzy edges. In Lisp's case the definition is relatively clear: sexp, and having some way to represent code as rich data (lists or syntax objects or maybe special AST objects) rather than just strings.
"A Lisp" always refers to "a language in the Lisp family", just like how "a Java" can never make sense unless there is a family of *Javas*.
phalp · 2022-11-27 18:01
Since CL packages were mentioned, here's how they work: they're maps, used only by the reader, from strings to symbols. When a string that parses as a symbol is read, the reader looks up that string in the current package, and either returns the pre-existing symbol indicated by that package, or creates a new one and makes an entry for it in the package. Symbols can also be written like `foo:bar`, which will cause the reader to look `bar` up in the package `foo`, rather than the current package. Actually it works amazingly well for being so simple.
nv-elisp · 2022-11-27 20:08
> Which is crucial in a system such as Emacs, where there are tons of old or not-maintained packages, which require older dependencies, many of which were already updated in an incompatible way, and there’s a possibility of another package requiring newer version.
Not to detract from the sentiment here, but I don't find this to be the case generally. I would also argue that packages which are so unmaintained (age of the package doesn't matter) should either be adopted or rewritten. Letting software die can be healthy.
big_lentil · 2022-11-27 21:52
What the hell the shorthand mechanism is such a terrible hack. Why is it even considered seriously? Another Stallman brainfart I'm assuming.
The Lua method is obviously the most elegant and simple solution. I wonder if it could be implemented in emacs. We already have closures so it shouldn't be outside the realm of possibility.
deaddyfreddy · 2022-11-28 11:51
> Clojure is very different from Lisp internally.
I don't think that car/cdr thing matter these days, hardly any working programmer ever used IBM 704. Besides that, thinking about internal representation of data structures sounds like time-wasting (most of the time), so `first`/`rest` makes much more sense in this case. So, from the pragmatic point of view, Clojure is lispy enough to get things done, the rest is nothing more than a kind of cult.
deaddyfreddy · 2022-11-28 11:54
When "true lispers" try to insult Clojure for being "not lisp" I usually beat back with "who cares, at least I can have a dayjob in it".
_viz_ · 2022-11-28 16:19
Emacs indeed does not have reader macros. Backquotes are a specific case in the lisp reader where `(...) gets changed to (` (...)), I forget the exact conversion.
github-alphapapa · 2022-11-28 20:57
Hard to argue with that. ;)
arthurno1 · 2022-11-28 21:18
It is a bit more involved, I just took a look at it. It looks neat. They rewrite lists. I don't want to use backquotes and macros; otherwise, I could just write a macro to rewrite names.
I ended up with something similar, though :-), just not quite. I do it with a function. I just rewrite html tags, attributes, and entities in the list returned from the 'read', and pass that to eval-defun & co- and let Emacs do the rest. It is slower than what they do, but it seems to work fine. I haven't done some extensive testing, but a few simple cases where I mixed my "shtml" with lisp calls worked well, actually better than I was expecting it myself. Can't rewrite 'map' 😀, but it is not commonly used html tag, so I can live typing manually shtml-map.