I have hacked a considerable amount in both Elisp and CL and I can state that I actually prefer the way Elisp does some things over the way Common Lisp does--this is not to say that CL does things the wrong way--the matter is that they have different purposes. Emacs combined with Elisp in itself constitutes a complete programming system; all of its components are designed around it.
The language being integrated into Emacs makes writing Elisp programs a very fluid and intuitive experience: things like the fact that the documentation and the place where a function was defined is available at any time makes /understanding/ the system easy, and the actual documentation itself is often quite well written, and the Info manuals will most often explain everything you need to know about a package. Common Lisp+SLIME shares some of this convenience, but not to the extent that Elisp truly does.
Certain points like the fact that Emacs isn't multithreaded are thrown around by people who don't have the intuition that multithreading isn't the right thing for a lot of applications. The added complexity that multithreading would add to Emacs would seriously outweigh the usefulness it would provide. Emacs already has a decent process model, and having to deal with only a single shared state makes programs much cleaner.
At the very least if it all comes down to a dick measuring contest, the base GNU Emacs provides 100000000x more utility in its packages in a fraction of the memory space than VS code or Vim ever will. Emacs has its fair share of killer apps like Magit that provide such a clean interface to something that it makes using it worth it for that alone.
I disagree with this point. Emacs does not have a useful process model, or at least it cannot be used to the full extend, because of shared global mutable state. This is exactly the issue, not a practical thing. If it were not for all the usage of mutable (and mutated) global state, Emacs could actually benefit from running many things concurrently, without annoying users with blocking behavior.
This is of course a huge task to refactor Emacs like that. I can only hope, that some day we will get there, because I see it as one fatal flaw, that could over time kill Emacs. Yes, Emacs as it is is super useful, but more and more things come up, that will be better off running concurrently and in parallel. Just to name a few: Package compilation, waiting for LSP stuff, anything that waits for network, like tramp, running source blocks in org-mode (org-babel), syntax highlighting of big files, magit stuff like rendering huge diffs in a magit status buffer ...
All of those things could benefit from being able to use multiple cores and improve Emacs' snappiness and speed. All of these come before even changing anything about elisp the language.
It is somewhat cumbersome, no doubt, but for all of the code that didn't decide to use that and can easily cause emacs to stall, I see no reason to think we won't have as much or more problems with multiple threads.
GNU Emacs has a lot of applications where it is the right thing. It's no longer the simple editor. It comes with more than a million lines of Lisp code implementing all kinds of complex features: like various network client applications, IDEs, ...
> Common Lisp+SLIME shares some of this convenience, but not to the extent that Elisp truly does
SLIME is mostly implemented in Emacs Lisp. A lot of other Lisp systems can locate all source code and all documentation. It's not so much a special feature of Emacs Lisp, but its development environment. It's also not necessary that the IDE and Lisp runs in the same process / same machine to be able to look up documentation and code. It may be convenient in GNU Emacs, but any such editor can provide such features for programming language implementations.
Multi-threading has landed in emacs anyway, by the way: https://www.gnu.org/software/emacs/manual/html_node/elisp/Th...
I theoretically understand this but having to deal with company-mode providers that, when they start performing badly, start hanging everything is not fun!
Obviously thread-count and async-codestyle-ease are not the same thing, but given the world of LSPs and plugins that do I/O on the main thread (this is a big enough reason to have async interfaces that are actually used) it would be good to have some effort spent there
Maybe for speed, `completion-at-point` would keep a fairly recent `dump-emacs-portable` image, and spin up external processes using that, with has the bonus that the completion-at-point-functions get to inspect current state.
I think that all (or a lot of?) the Emacs niceties could be grafted into a hypothetical EMACS package in Common Lisp. There’s no reason why an Emacs in Common Lisp wouldn’t still be able to jump to a definition, or to documentation, or whatever. It could still implement advice.
And the entire thing would be hackable at runtime, unlike the current Emacs situation where everything but the core runtime is hackable. And there would be packages instead of having to prefix every package’s function with the package name.
Common Lisp is definitely not perfect, but it would probably be a better base for Emacs than Elisp is. Elisp is not bad — at least it’s a Lisp, not Lua or Javascript — but it’s really not great.
Sorry if you were confused by my wording; SLIME is able to do all of this--and I am not intending to badmouth SLIME either, it's a very great and well-featured system. However, it plays the odd role of having to bridge the gap between Emacs, and the various CL implementations it's meant to support. Things like documentation of functions really come down to the implementation you're using. The de-facto source of documentation for Common Lisp is the HyperSpec, which is a collection of HTML documents. If it doesn't already exist I would like to write a hack to make these documents render inside Emacs itself.
I think I should clarify the idea that Common Lisp itself is merely a /language/. Unless you're only writing strictly ANSI CL, real programs depend on the facilities provided by the implementation; it isn't a complete programming system until you give it an environment. SBCL+SLIME, or Allegro or LispWorks or a Lisp machine constitute full programming systems in the same way Emacs+Elisp does by itself.
>And the entire thing would be hackable at runtime, unlike the current Emacs situation where everything but the core runtime is hackable.
Ever since Elisp has begun to be compiled into native code, I've become hopeful of the idea that eventually the core components written in C will eventually be subsumed by Elisp itself. However, I am also concerned that this will also degrade the overall performance of the system; not because compiled Elisp wouldn't be performant enough but because hackers might be likely to rewrite these components in a negligent way (the same way they have written modules which are the source of many of the relevant complaints, like LSP and company-mode)--see my other comment in this thread about the internals of the Lisp machine system.
However, having said that, I think a good enough majority of the runtime is hackable that it escapes being a problem. Much of the window system, for example is exposed to Elisp: one of my projects recently has been to write a drop-in replacement for the X window context menus that spawn text frames instead.
>And there would be packages instead of having to prefix every package’s function with the package name.
Packages with namespaces are one thing that would have been nice to have, but it's lack of them is well entrenched enough at this point to remain, and it isn't really a problem once you get used to it.
Performance is something that needs to be done well in this target domain, and it fails
> the base GNU Emacs provides 100000000x more utility in its packages in a fraction of the memory space than VS code or Vim ever will. Emacs has its fair share of killer apps like Magit that provide such a clean interface to something that it makes using it worth it for that alone
And now that Microsoft created LSP (IMO not because they're kind hearted but as a totally dick move to piss off JetBrains who was gaining too much developers momentum and becoming a threat to the "developers, developers, developers" mantra) and that Emacs supports LSP, suddenly those things an IDE did really better than Emacs are much smaller. I'm not saying there aren't a few things an IDE from JetBrains shall be better at than Emacs for a particular language: but on average the gap on those things got way narrower. And Emacs can do a shitload of things an IDE doesn't: configuration/tailoring to your way of working comes to mind. I wrote an IntelliJ plugin back in the days: not fun. I much prefer to write elisp to enhance Emacs.
I was using IntelliJ IDEA back before some commenting here were born: I was an early IntelliJ IDEA adopter (when it was barely usable on Linux btw). But I never stopped using Emacs.
Every other IDE became slower and "piggyer" at a rate outpacing the now dog-slow advances in CPU/RAM on personal computers (I'm running an AMD 7700X atm, so not too bad of a machine). Meanwhile at every single release Emacs became more efficient. The switch to "native complication" was a gigantic speed boost.
As I like to point out: the "Emacs meaning Eight Megabytes And Constantly Swapping" joke was true back in the frigging nineties. Yup, on a 486 with 8 MB of RAM it was quite something to run Emacs.
But nowadays we all have about 16 to 64 GB of RAM on our systems. And Emacs is still Emacs.
When something survives decades and has stuff like Magit and org-mode which many revere, it has to do something right.
If there's a problem with elisp is that it's... Old? But it did survive. It is usable. It's problems and how to work around them are well known.
And it's rock stable. My custom Emacs/elisp code configuration is about 3 000 lines of elisp. I think I made one change/commit in six months to my Emacs configuration. It's that solid.
> At the very least if it all comes down to a dick measuring contest ...
Oh also... At times I have Emacs' uptime surpassing that possible of a Windows consumer OS (which needs to be rebooted regularly due to mandatory updates).
Basically the only time when I reinstall Emacs is when I upgrade to either the new Debian stable distro or when I upgrade to a new PC: when it comes out, I install it (I prefer to install from scratch, YMMV) and then use the opportunity to fetch the latest Emacs and compile it from source. I don't remember the last time I did it: it was when Debian 12 stable came out.
Elisp is either a scripting language for a text editor,
OR
a fully-featured programming language for doing All The Things.
Instead of returning a data structure of the match results (eg from a call to match-string), the match results are mutated in global memory and accessed in separate function calls. This is both less functional in style and more error prone. For example, if save-match-data is not used appropriately, then library functions can trample on the match data which a higher level function is in the middle of using.
But in some other parts it reads like two or more personalities stuck in the same body shouting at each other using the same mouth: EmacsLisp Isn't Scheme
This, from my highly unscientific sample, is far and away the most popular reason EmacsLisp sucks. Well, that’s good to know. EmacsLisp is also not Perl, or COBOL, or IBM 1130 assembler, or a bicycle, or an orange. Thanks for the help! ;; Also, I need the ~save-match-data~ because apparently
;; ~split-string~ messes up the match information. I spent hours
;; debugging this.The Emacs data model sucks. There are APIs that do who-knows-what combined with your personal extensions that modify behaviour who-knows-how, figuring out how to describe UI components is no fun, text editing is surprisingly hard from a programmers perspective, there are decades of accumulated different ways of doing things and it is unclear where to start or what has been obsoleted. The names made sense in the 70s but unfortunately it is 2024 and "Windows" means something different now. I wouldn't even exactly blame Emacs for any of this since some of it seems to be essential complexity of the domain.
EDIT Example, picked completely at random:
https://github.com/clojure-emacs/cider/tree/master/dev
(defun cider-tramp-prefix (&optional buffer)
"Use the filename for BUFFER to determine a tramp prefix.
Defaults to the current buffer. Return the tramp prefix, or nil
if BUFFER is local."
(let* ((buffer (or buffer (current-buffer)))
(name (or (buffer-file-name buffer)
(with-current-buffer buffer
default-directory))))
(when (tramp-tramp-file-p name)
(with-parsed-tramp-file-name name v
(with-no-warnings
(cider-make-tramp-prefix v-method v-user v-host v-port))))))
Here is a random function from CIDER. The code is simple enough, the lisp is no problem. Immediately we see we're interacting from one extension to another, have to understand Emacs buffers, need to know how warnings are displayed, have to understand parsing as a domain, and appear to have a network involved. That is a lot of work to debug one function when something is misbehaving. Not an unreasonable situation, but nonetheless a barrier. Then on top of that I have to go look up what let* is and why it is presumably different from let. One more thing I don't want to do. Emacs lisp sucks.EDITEDIT Tramp isn't an extension, it is part of core emacs. We live and learn.
EDITEDITEDIT Spoke too quickly, it looks like it is a GNU-supported extension. This is the sort of trivia that got me using Doom Emacs.
I don't think this is a problem for elisp; isn't `let*` in Common Lisp as well?
I don't think they can, my complaints are that I have to spend too much time reading the manual and source code. Reading the manual and source code will not help resolve that.
The article lists a few defaults of elisp that aren't shared by all lisps. What do you mean by this sentence?
You can level complaints against Elisp. You can level complaints against anything. They aren't a big deal - Elisp supports variables, loops and if statements and that is enough to implement a text editor to a first approximation.
If the slate was wiped clean, the Emacs community would probably prefer that Emacs was written with Common Lisp. Then Emacs wouldn't need its own lisp reference manual.
Don't modern languages require you to also look up definitions of functions. Learning peculiarities like this in Common Lisp (eg equality) really opened my eyes to how much "magic" there is modern high level languages. Personally I dont like magic and lisps tend to be the most magic free high level languages
It's just one damned anachronism after another.
The language used to manipulate the data model is almost irrelevant. It's probable that the initiates within the priesthood know it all, but the hoi-polloi certainly don't; and we probably don't have the time to find and read all the docs just to use an editor with a simple customization. It's exclusionary and there's an immense barrier to entry, whether it's elisp or bananas-lang.
I take great care with my VSCode extensions and their configuration. I likewise take great care with neovim and having it set up properly.
Modern Emacs Lisp is easily the best environment among my daily drivers for interacting with my editor in real time.
Of anything modern I only know Zed a little: Zed in theory might be better than Emacs.
Outside of maybe Zed, which I haven’t mastered, Emacs Lisp is bar nothing the best tool-making tool for serious hackers.
[1]: https://zed.dev/
Nope.
There are some surprises. And I do think common lisp has a lot of better parts. But, at the end of the day I find elisp fine for a scripting like language. And I love how accessible every line of elisp in my machine is.
And that's usually good, because the whole point of Emacs is to make it easy to inspect and manipulate it. It's one case where information hiding and encapsulation - including lexical scope - get annoying very quickly.
And I would have asked about Guile too but that is another matter.
I think LEM's approach is better here in utilizing SDL and common lisp. If they write an ELisp interpreter and somehow translate Emacs editor api so plugins would work in LEM too, that would be ideal.
https://lem-project.github.io/usage/usage/
(development notes: https://lisp-journey.gitlab.io/blog/oh-no-i-started-a-magit-...)
Lem has:
- syntax highlighting and language-specific commands (linter etc) for many languages: Common Lisp of course, but also Python, Rust, C, Erlang… JSON, HTML, markdown (including interactive preview in a browser)… a directory mode…
- LSP should just work
- treesitter is a WIP
- graphical and terminal interfaces- integrated terminal (libvterm)
- project-related commands, interactive grep, tabs, a side-bar project explorer, keyboard macros, multiple cursors, built-in help (to a certain extent), mouse support, transparent background…
Regarding Guile - I am familiar with it since I use GNU Guix. I think it is one of the more practical Scheme implementations with its current ecosystem.
Good luck!
Libraries that help with that, even though the major underlying structure isn't immutable data structures make Emacs Lisp bearable are: s.el, ht.el, dash.el It would be great if there was namespacing and less global state pollution.
Of course if you want to integrate with the rest of the Emacs ecosystem and you want some libraries that help you out make things nice means learning a whole different ballgame. Like wanting to use the great transient.el. That's super stateful and based on eieio.el. (Although transient.el is relatively good about hiding that behind a good API surface.)
Overall, even though I wish it was based on a functional core and Clojure's immutable data structure, concurrency, namespacing and its great EDN reader, I just accept the pragmatism on the human scale that if I want a great text based interface that interacts with the rest of my text driven workflow Emacs is a good choice and Emacs Lisp is acceptable.
At least there's the "rx" DSL as an alternative.
I actually get a lot of utility out of eww, it's not just a novelty for me. I can browse online documentation without a DM, or if I do have a DM, without moving my hand to the mouse. It's not just a novelty.
It is getting increasingly difficult to use; much like emacs the web has also transitioned from its original intention (hypertext documents) to a bloated app development platform and it's increasingly unfriendly and difficult to use with simple browsers. Even so, there are still websites worth visiting that are usable from trivial browsers as long as you avoid the many apps masquerading as webpages.
I do too. And the underlying shr rendering library is invaluable when so much of email traffic is text/html. A bunch of other stuff like mastodon.el and devdoc.el rely on it too.
> It is getting increasingly difficult to use;
In my experience it's not that much worse than it was 10 years ago. By the time eww came about the JS-less browsing ship has long sailed. The sort of stuff that was working back then still tends to work now. We lost some good sites like the BBC text-only mode but also gained some nice text proxies like 68k.news and brutalist.report.
Such poppycock. Clearly marking functions with side effects as such is not stigmatization, it's common sense. Don't take the sloppiness of other language cultures for the norm, although statistically it may well be. Too many people already think procedural object soup is how things should be.
On my old Lisp Machine, Zmacs ran in a multi-threaded Lisp roughly in the early 80s. Multiple Zmacs windows each had their own thread. Applications had their own thread. GC has its own threads. Even the mouse has its own thread. It still works that way.
But you don't need a Lisp Machine OS with threaded Lisp for that. Many current implementations of Lisp support multi-threading. An example is SBCL, a natively compiled Common Lisp, which supports native threads on its platforms. Thus an editor written on top of SBCL could make use of that. IDEs of LispWorks and Allegro CL are also multi-threaded and they have their own implementations of Emacs, written in Common Lisp.
Compare with GNU Emacs, where Emacs Lisp lacks this feature. Wouldn't you want an mail thread not block the rest of Lisp code? Some Lisp action in the REPL not to block the rest of Lisp code?
Multi-threaded Lisp architectures are more complex. Emacs Lisp tried to be simple. But the stuff written in it long ago was outgrowing the provided simplicity. For a capable extension language it was "good enough" for a long time. For an "application development platform" it's not. Lack of multi-threading in Emacs Lisp and the GNU Emacs architecture is an example.
I wonder what the processing architecture of those Lisp machines were like. Did their "cpu"(?) had special circuitry for implementing lists, CAR and CDR? Was this multi-threaded-ness something built-in in hardware?
Emacs Lisp does have threads; https://www.gnu.org/software/emacs/manual/html_node/elisp/Th...
SBCL (and it's one of the fastest Common Lisps out there) ran MCCLIM at glacial speeds in my n270 netbook, kinda like a busy Pentium MMX running Windows 98 where you could see Win32 controls redrawing themselves. OTOH, GNU Emacs' multithreading sucks, but at least the UI it's miles ahead on responsiveness.
If memory serves, the idea for ELisp was to eventually become the "proper" Lisp for system programming. At the time, people used the word "Lisp" very liberally, in a way how we today might use "high-level programming language". And, in a way, Guile was supposed to become that, but as is the case with some such initiatives (eg. Hurd) it never gathered enough momentum to replace the predecessor that was "good enough" and was continuously kept afloat with more and more upgrades.
As for the larger set of complaints about ELisp... it was good for a very long time, but it's getting old. There are many programming practices that are difficult to incorporate into the language. There are what we collectively came to believe to be programming anti-patterns that are encoded into the core of the language. And it's hard to do a proper face-lift because it will inevitably break a lot of old code. Also, doing such a face-lift you'd always be perplexed by the idea of what if a few years from now you could do an even better job of rewriting it into something even better? Knowing that one such change will put a ring on you, perhaps for the rest of your life, it's hard to make the step. Also, there are and have been many attempts of moving away from ELisp, and none really gained much traction among Emacs users. So, it's hard to imagine that the next such attempt will succeed.
My fear in this regard is that one day, instead of evolving and replacing with something better, we'll be reduced to using junk like VSCode due to some underlying system aging out completely. Similar to what happened to Firefox when it lost its ability to house extensions. I pray this day never comes, but, in practical terms, it means that at some point the community of ELisp users needs to cut losses and embrace the loss of older libraries to move to a revamped ELisp2 or w/e it will be called.