📓 programming/elisp-sucks.md by @karlicoss

Table of Contents

Emacs is often praised for Elisp, which is presented as some sort of silver bullet and magical tool that solves everything.
In my opinion, this raises the expectations too high, and then you end up disappointed when you struggle to do very simple things (and you even end up having impostor thoughts).
Emacs is possibly the most malleable environment out there, I use it all the time and enjoy hacking it, however I like the result, not the process. I often feel that I have to do it despite Elisp.

The purpose of this not is not just to rant, but

[2019-10-19] [how it started](https://twitter.com/karlicoss/status/1185607527460937729 )

I just started writing down reasons why elisp sucks every time I'm frustrated, so I can let off the steam instead of shitposting and ranting. It might actually result into something useful.

Some of my context.

standard library

Disclaimer: different people obviously engage with different parts of standard library so YYMV.

very inconsistent naming

Of course naming is a hard problem, but it’s not that big of an issue in some other languages:

In untyped language like Elisp all bets are off, the only way to find out how to use the object are

hmm how to arrange it with ‘documentation’ section?

[2021-01-25] to be fair to Elisp, I’m finding clojure suffering from the same problem [[clojure]] [[lisp]]

Although naming is better subjectively (possibly because the language is yonger), it’s still a mess of untyped walls of text

The nice thing clojure docs have are the community provided examples

I hope this is a constructive thing I (or someone else) can borrow from Clojure for Elisp.

list manipulation routines are bad

This is very important because dealing with list-like structures is a massive part of any programming.

cadr cdar cadddr – what the fuck.

it’s beautiful that matter is made out of atoms
it’s not great if you have to think about individual atoms to move your fingers

[2021-01-25] the short answer is to use dash.el

I mean, simply compare its reference with the mess the builtin documentation is.

string manipulation is bad

Similarly, something we have to deal with all the time, and especially in a text editor.

[2021-01-25] the short answer is to use s.el

error handling is bad

And again, a very important part of programming – how to make your programs behave predictably under any circumstances?

[2020-02-27] regexps are case sensitive

https://www.reddit.com/r/emacs/comments/5jip0g/strange_replaceregexpinstring_behavior/

So, if you want case sensitive, do
(let ((case-fold-search nil))
     (replace-regexp-in-string "my" "your" "mycat.txt" t t)
)

fucking hell.. regexes in elisp are case sensitive, and that’s controlled by a fucking variable. jesus

[2021-01-25] on the other hand, in a way it’s nice that it’s easily customizable without having to think too hard about APIs

as long as the author extracted the variable in defvar, it’s hackable

why elisp sucks: no check_output / check_call [[elisp]]

https://github.com/karlicoss/subprocess.el/blob/master/subprocess.el

documentation

Somehow I almost never manage to figure out (or at least much left often comparing to other PLs).
Thankfully, in emacs you can use find-function and just read the source code, it’s often easier.

no types

for the context, I don’t mean strict/static types or whatever. I just want something like optional gradual typing, like #mypy

sort of hard to express… but basically

maybe it’s just org-mode thing since this is the only ‘big’ elisp system I worked with
example with org-element-set/adopt in exobrain source code
if it was language with ‘real’ types, it would be easy to dir() or somethign to see what methods are available
but maybe it would be less flexible, I dunno
on the other hands it means that you can always hack it somehow and then maybe figure out ‘proper’
but discoverability really suffers

extra links

[2019-10-18] EmacsWiki: Why Does Elisp Suck

defaul error reporting sucks [[elisp]]

e.g. try making a typo here. by default it dumps a single message with absolutely no context whatsoever (file/line number)

(advice-add #'org-org-section         :befoire #'exobrain/before-org-org-section)

stacktrace is pretty useful too

[2019-12-26] [Fuck Elisp, issue 20191226](https://twitter.com/karlicoss/status/1210252416479838208 )

Actually if lisp is so extensible and you can do anything home come I can’t write my emacs config in Python?? [[lisp]]

[2019-10-20] Output Functions - GNU Emacs Lisp Reference Manual [[elisp]] [[lisp]]

https://www.gnu.org/software/emacs/manual/html_node/elisp/Output-Functions.html#Output-Functions

why lisp sucks

why elisp sucks: buffer-size [[elisp]]

doesn’t take an argument so need with-current-buffer

https://www.gnu.org/software/emacs/manual/html_node/eintr/Buffer-Size-_0026-Locations.html

can’t jump to source code because it’s in C?

whereas buffer-filename takes optional argument
https://www.gnu.org/software/emacs/manual/html_node/elisp/Buffer-File-Name.html

[2021-01-16] gnu.org/software/emacs/manual/htmlnode/eintr/else.html [[elisp]]

Note that the different levels of indentation make it easy to distinguish the then-part from the else-part.

ugh, this is bullshit. how the fuck is this makes it easier.
e.g. if you swap if and else clauses, indentation changes

[2019-12-26] [Do you have any resources to read? I’ve been genuinely looking for ‘modern elisp’ guides, but failed to find anything decent, quite opposite, people opposing use of dash/s/etc.](https://twitter.com/karlicoss/status/1210287560649584642 )

[2019-12-26] [Also, I had to read reasonable amount of elisp (org-mode mostly, but other packages as well), and I really fail to see features you mentioned in use. Very often it’s verbose car/cdr mess lacking abstractions and basic code reuse.](https://twitter.com/karlicoss/status/1210288518637006849 )

[2019-12-26] [I appreciate eshell/monkey patching/edebug, but that doesn’t really strike me as that good. I mean, most modern interpreted languages have this, unless I’m missing on something?](https://twitter.com/karlicoss/status/1210287248467517440 )

things common to lisp in general (mostly paren based stuff?) [[lisp]]

awkward indentation apparently aids parinfer in placing parens, however sometimes it results in code errors without noticing

why lisp sucks: reliance on tabulation (e.g. if you change let to let* everything shifts)

why style sucks: comments after )))) (on last line). too many git changes when you add one line

lisp: discourages intermediate variables

let bindings struct is really annoying, which discourages naming variables

собственно мотивационный пример на питоне

def normalize(vec):
   x, y = vec
   len = sqrt(x ** 2 + y ** 2)
   if len == 0:
       raise RuntimeError(f'bad vector {vec}')

   nx = x / len
   ny = y / len
   return (nx, ny)

на елиспе

(defun normalize (vec)
  (let* ((x   (car vec))
         (y   (cdr vec)))
         (len (sqrt (* x x) (* y y))))
    (if (=0 len)
        (error (format "bad vector %s" vec)))
    (let* ((nx (/ x len))
           (ny (/ y len)))
      `(,nx ,ny)))

а я хочу как-то так

(defun normalize (vec)
  (let' (x y) vec) ;; can't do in elisp?? maybe with cl-destructuring-bind...
  (let' len   (sqrt (* x x) (* y y)))
  (if (= 0 len)
      (error (format "bad vector %s" vec))
  (let' nx (/ x len)
        ny (/ y len))
  `(,nx ,ny)))

наверное это можно добиться если добавить какую-нибудь магию вроде макроса (scope ...), который эти let' правильно интерпретирует

good parts

good: parinfer sometimes is quite nice [[elisp]]

sometimes though it arbitrarily reararnges parens. e..g I have to be really careful when pasting big source blocks from elsewhere

good parts [[elisp]] [[toblog]]

advice-patch

good things: hacking on the config while loading stuff via eval-defun [[elisp]]

i.e. I think people who advocate for REPL are pitching for a completely wrong thing – I want to keep my code tidy, it’s just nice to execute it instantly

why elisp is good: eshell, easy to mess with IDE [[elisp]]

to be fair, same is probably true for e.g. sublime?

appreciation why is something good is hard, you don’t notice it as easy as bad things

let’s compare: e.g. vimscript. When I used vim I haven’t even attempted to customize it, I tried once and the whole thing was just futile.

Write a post comparing what elisp/common lisp offers and compare to python [[toblog]] [[python]] [[lisp]] [[elisp]]

"How do we kill Elisp?" [[elisp]] [[toblog]]

when I paste stuff from org-mode source to experiment, I often end up with ruined code (as in, broken code!)

example: (defun org-html-format-headline-default-function
maybe I need to disable parinfer during pasting, not sure

debugging: very often it’s much easier to copy over the function and use output debug [[elisp]]

also use with-current-buffer and a separate buffer – oftern much easier than repl…

try finding out how to take nth character of a string [[elisp_sucks]]

[2021-02-06] elisp - How to determine if the current character is a letter - Emacs Stack Exchange [[elisp_sucks]]

n case you were very concerned about national characters and precise treatment of Unicode character classes, then the only solution I was able to find so far is the Python regex library. Both grep and Perl (to my utter surprise!) didn't do the job properly.

I haven’t written proper Elisp libraries/packages, only hacks/function/etc, so apologise I am missing out on some important aspects [[elisp]]

Structure as problem– solution

E.g. bad docs? Enjoy easy jump-to-source

problem with car and cdr is not that they are the standard building blocks, but that they are abused [[elisp]]

in the same vein consistently using head . tail . tail in Haskell to access the third element would be insane (I’m not sure if it’s actually common though)