DEV Community

100 Languages Speedrun: Episode 86: Emacs Lisp

Tomasz Wegrzanowski on February 11, 2022

The Editor Wars are long over. TextMate-style editors (Sublime Text, Atom, VSCode) won. Language-specific editors like Jupyter, Android Studio, and...
 
taw profile image
Tomasz Wegrzanowski

VSCode doesn't have builtin keyboard macros, but there are packages for it.

I suspect most things you'd do with keyboard macros are better done with multiple cursors.

Collapse
 
cben profile image
Beni Cherniavsky-Paskin • Edited

to read a file we need to create "temporary buffer", insert file contents into that buffer, then read the buffer contents

Not so strange in a text editor. I know you're deliberately sticking to standalone CLI scripts in this series to avoid comparing languages' own environments, but for Elisp that really stretches it out of its niche of scripting Emacs itself :-)

Many weird choices Elisp made are actually very interesting as an exercise in "Language-Oriented Programming". A central goal was to maximize dual-use functions that one may invoke as editor commands OR call programmatically.

Consider string/regexp search function. In "normal" languages, it may take the string to search in, the pattern, some flags (e.g. case_sensitive) -> and return an index.
In Elisp, it operates on current buffer, it has side effect of moving the cursor(!), and case sensitivity is controlled by a config variable. Which is sensible for interactive search command, but how is a good API style?!
Well, that's gonna be a repeating pain with most dual-use functions, right?

Emacs mitigates that by adding constructs to combine such functions:

  • what if you wanted to search within other string?
    => Several constructs like with-temp-buffer — compare to Unix standardizing on stdin/out and providing redirection facility in shell!
    (So see, a read-file function returning a string is not that useful. For any serious manipulation you'd upgrade it to a buffer anyway.)

  • what if you didn't want side effects?
    => Several constructs like save-excursions restore previous state. (originally no Unix analogue, nowdays that's a bit like running in a container and deciding later whether to commit the modified FS.)

  • Global case-fold-search config var is obviously not enough :-(
    => Unique scoping concept: buffer-local variables! E.g. set it sensitive in a Python buffer, but ignore case in english prose buffer.
    => Dynamic scoping?! It's weird and mathematically broken (and historically comes from old lisps) but it does make any function that references a "global" variable locally configurable: (let ((case-fold-search t)) (search-forward ...))

It's not all roses. In particular tons of elisp code doing searches and cursor movements for ad-hoc "parsing" of nearby context stinks... A code editor really should have decent DSLs for actual parsing, which for a looong time emacs really lacked :-(

So yes, pretty bad as general-purpose language, but an interesting point in language design.

Collapse
 
cben profile image
Beni Cherniavsky-Paskin

It gets more interesting as a system. "GUI-phobia" accusation is true but it did provide, at its time, a very advanced TUI prototyping environment. It had a DOM, with redisplay taken care of for you, very flexible bindings from events (key sequences, mouse) to handler functions, and embedded interpreter for writing these handlers, and tight devel loop by modifying the system live as you're using it.
All this in many ways resembles modern browsers with DOM->JS handlers!

(Of course, it can't compete with modern browsers on layout/styling/graphics. Nor on flashy devtools. => You're right that nowdays VSCode is better choice for reusing web skills, and that on number of devs alone, elisp has no chance to compete in long run.)

Emacs had more on-ramps from "end-user" to programmer than modern browsers — it never wanted to split between page author / user. E.g. you can start from simple macro recording, later convert a macro to Elisp code, later edit it to add some conditionals/loops. You can override/"advise" almost any builtin function.
In comparison, even VSCode has much more of boundary between core and "extensions" :-( Though it has not-bad reasons to do that! It can provide more of "app-store" experience installing extensions. Running in external process with LSP protocol finally solved E*L problem to E+L (and both Emacs and Vi are now benefitting from LSP)

Collapse
 
vincentjgoh profile image
vincentjgoh

why do we need to do this silliness like (apply 'prints (cdr args)) instead of (prints &rest (cdr args)) or (prints . (cdr args))

You know why. You wrote this in a way where you want to pass in individual arguments, but then use cdr which returns a list, which is not the same thing? Like, you've very clearly made a programming decision here that would intentionally break. You clearly know how to use the map functions, so why wouldn't you use those instead, instead of a recursive solution? And map is a perfectly fine name for a class of functions; they map a function onto a list.

I'm not gonna argue that elisp is somehow the most accessible or best language to do things in--it carries a tonne of historical baggage with it like lots of other languages do--but at the very least, you can't misuse it and then say that's the fault of the language. Every language has its context. This is one that's inside an editor and is meant mainly to augment the functionality of the editor; other things are possible (I mean, that's a pretty decent wordle clone in very little space) but it's not really fair to compare its general purpose utility to other languages when it's not a general purpose language at all. (The extended functionality of emacs is definitely due to the skill of the plugin writers. Sometimes I'm amazed at something like emacs-hydra. Wrangling macros like that isn't easy.)

That said, this was fun. I'm looking forward to reading through the other languages. I hope you're at least this critical of C++. :D

Collapse
 
taw profile image
Tomasz Wegrzanowski

map is a perfectly fine name, as would be maplist or listmap or so. mapcar is really weird.

The series is close to 100 episodes, and I have very few free slots left, so I don't think C++ will make it.

Collapse
 
vincentjgoh profile image
vincentjgoh

mapcar actually makes the most sense to me—it tells you how it's going to apply the function. For once, the documentation on the official manual page is very useful: if you use mapcar with cons and 2 lists, it cons the cars of each list together. In the context of a lisp, it's actually very clear. (mapconcat too, actually. It does what you'd expect.)

I find mapcan and mapc much less obvious names. mapc works just like mapcar but only for the side effects? Useful, but why is that what it means? mapcan? Why is it called that? It returns a single list of all the results which themselves must have been lists, so it's flattening the answer down. Again, useful, but that name is random as far as I'm concerned.

Collapse
 
ochsec profile image
Chris Ochsenreither • Edited

I probably would have been into Emacs Lisp if I was programming when it was new-ish. Wikipedia says it was released in 1985. Back then, you were most likely siloed on your own computer and making various types of programs and games within emacs would have been fun (maybe with your friend who was actually in the room). I took a course in Racket but I find languages like F# much easier to read, if I'm looking for something functional.

Collapse
 
sre profile image
SREagle

The article begins with "The Editor Wars are long over." - but this article also got by far the most comments, referencing each other.

This goes to show that there seems nothing more divisive than the choice of the most basic tool of a computer user: the editor.

Personal choice is king, and some tolerance for the choice of others goes a long way.
But man, this is fun to follow... 🍿

BTW: I like the 'hot take' approach of the articles, even while disagreeing on most languages I happen to know better. "No fanboying" indeed! 👍

Collapse
 
taw profile image
Tomasz Wegrzanowski
 
andreyorst profile image
Andrey Orst

I can highly recommend trying out Kakoune editor. It is built around multiple selections, and it's the best implementation of the feature I've seen so far. Kakoune combines macros, regex, and multiple selections into a very powerful editing language inspired by Vim

 
taw profile image
Tomasz Wegrzanowski

You can do next matching regex select for multicursor too.

I'm not really sure what's the use case for macros. Multicursor is a crazy powerful feature, so I really don't want any editor without it (unless I'm over ssh and all they have is nano or mcedit). Emacs doesn't have it, and I don't know how good third party packages that add it are.

If something is too complicated for multicursor, then you should probably write a proper extension with some interface for it.

I'm not really sure what kind of tasks would fall in the middle ground - too complex for multicursor, but not worth writing proper extension command for.

Collapse
 
taw profile image
Tomasz Wegrzanowski

Emacs ecosystem is fairly small compared with VSCode ecosystem. Is there Github Copilot for Emacs? Jupyter for Emacs? Syntax highlighting for 90% of the languages I covered for Emacs?

If ecosystem is what you're after, you're using a wrong editor.

If you're already an Emacs user, with tons of customizations you've created for yourself, you might just as well keep using it, but I'd definitely not recommend it for anyone new.

Collapse
 
andreyorst profile image
Andrey Orst

Emacs ecosystem is fairly small compared with VSCode ecosystem.

That's a bold statement, that needs to be backed up at least by something. VSCode is fairly popular right now, so its package base grows rapidly, but new packages pop daily for Emacs as well. Emacs has packages for a lot of things VSCode probably would not even go for, like an NES emulator, or a tool to order salads from a specific restaurant.

Is there Github Copilot for Emacs?

Not yet, as Copilot is in closed beta, but there are already 3 other packages that implement what Copilot does, except those are FOSS.

Jupyter for Emacs?

Yes, yes. Actually, Org Mode can do everything Jupiter can, and with much more languages than Jupiter.

Syntax highlighting for 90% of the languages I covered for Emacs?

Oh boy. Because I have nothing more important to do this sunday morning, I've went and checked almost all languages you've written about:

  • ✅ Python
  • ✅ Emojicode
  • ✅ CSS
  • ✅ Lua
  • ✅ Kotlin
  • ✅ Tcl/Tk
  • ✅ Sed and Regular Expression FizzBuzz
  • ✅ Ada
  • ✅ Befunge
  • ✅ Tcsh
  • ✅ D
  • ✅ Arc
  • ✅ Awk
  • ✅ Octave
  • ✅ Rake
  • ✅ PLY Python Lex-Yacc
  • ✅ Julia
  • ✅ Forth
  • ✅ Clojure
  • ✅ XSLT
  • ✅ Ruby
  • ✅ Postscript
  • ✅ JQ
  • ✅ Raku (Perl 6)
  • ❌ Whenever
  • ✅ TeX
  • ✅ Verilog
  • ✅ SageMath
  • ✅ Fortran
  • ✅ Gherkin
  • ✅ Logo
  • ✅ Racket Scheme
  • ✅ Groovy
  • ✅ AppleScript
  • ✅ OCaml
  • ✅ BC
  • ✅ SQLite
  • ✅ Assembly
  • ✅ Prolog
  • ❌ Thue
  • ✅ M4
  • ✅ Elvish
  • ✅ Crystal
  • ✅ COBOL
  • ✅ R
  • ✅ Perl
  • ✅ QBasic
  • ✅ Haskell
  • ✅ PHP
  • ✅ Scala
  • ✅ XQuery
  • ✅ Smalltalk
  • ❌ Asciidots
  • ✅ POV-Ray
  • ✅ LLVM Intermediate Representation
  • ✅ CSVQ
  • ✅ ChucK
  • ✅ Xonsh
  • ❌ Io
  • ❌ Ioke
  • ✅ Wren
  • ❌ Factor
  • ❌ Windows Batch Files
  • ✅ Free Pascal
  • ❌ Jasmin
  • ❌ Designing New Esoteric Language Tuples
  • ✅ Elixir
  • ❌ Pyret
  • ✅ PowerShell
  • ❌ Lingua Romana Perligata
  • ❌ Linguagem Potigol
  • ✅ Emacs Lisp
  • ❌ Sidef

So the stats are - 73 languages total, 60 covered, 13 uncovered, which is 82%.
Not quite 90%, but I bet still much higher than you've expected.
I didn't search too deep, mostly included everything that shows in top google results or directly in the package manager.

If you're already an Emacs user, with tons of customizations you've created for yourself, you might just as well keep using it, but I'd definitely not recommend it for anyone new.

Yes. Emacs is a journey you need to come to by yourself. Simply because Emacs is a tool that you can truly make your own thing.

Thread Thread
 
taw profile image
Tomasz Wegrzanowski

Yeah, it's higher than I expected, but VSCode does all those plus 6 more (Io, Factor, Pyret, Linguagem Potigol, Asciidots, Windows Batch Files), getting it to 90%.

There's no sweetgreen, but there's NES emulators.

By simple count there are 33829 extensions in VSCode extension manager, 5241 on Sublime Text package manager, 5097 on Emacs MELPA.

This gap is only going to get widen, as there's a lot more people who can write JavaScript than Emacs Lisp. It's also quite easy to port stuff from the web to VSCode.

Thread Thread
 
andreyorst profile image
Andrey Orst

By simple count there are 33829 extensions in VSCode extension manager, 5241 on Sublime Text package manager, 5097 on Emacs MELPA.

I believe in quality, not quantity.

For instance, VSCode had three plugins for working with files over ftp protocol, and none of those worked as advertised, constantly getting de-synchronized and not being able to pull files. Emacs has one package that does it, and many more things for working with various remote file editing protocols, but the most important thing is that it works.

Emacs is already 36 years old, let's see how VSCode will do in 36 years :)

Collapse
 
fadhilradh profile image
Fadhil Radhian

Amazing journey right there!

Collapse
 
bbrtj profile image
bbrtj

VS code will either be abandoned or set aside by the new hotness in let's say 5 years. Many editors come and go yet Emacs and vi stick around. It makes much more sense to spend time developing a plugin in elisp or vimscript if you know you will basically be able use it indefinitely.