⭐ Elisp sucks (and can we make it suck less?)

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

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.

Table of Contents

standard library elisp

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

very inconsistent naming elisp

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

  • in C++/Java (OO languages), you can refer to the documentation of the objects' class, e.g. std::vector
    granted, someone has to generate the documentation in the first place, but in the worst case you can check the class' source code/header file
  • in Python/JS you can do the same (e.g. python's list docs)
    in addition, you can use the REPL (something like dir/vars) to discover which methods/properties the object has
  • Haskell is not OO, but you can use something like Hoogle to discover all functions that operate on a given data type

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

  • rely on the documentation (and it's a mess)
  • read the package source code to discover all the functions available, perhaps search over variable names
    this is usually what I have to resort to, even for builtin packages like org-mode

TODO [A] hmm how to arrange it with 'documentation' section? elisp

TODO [B] [2021-01-25] to be fair to Elisp, I'm finding clojure suffering from the same problem elispclojurelisp

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 elisp

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

TODO cadr cdar cadddr – what the fuck. elisp

CREATED: [2021-01-25]

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 elisp

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

string manipulation is bad elisp

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

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

[C] [2020-02-27] regexps are case sensitive elisp


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 elisp

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

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

documentation elisp

no types elisp

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

  • yes, elisp is very dynamic and it's kind of futile (and often counterproductive) to annotate everything with types
    but some things are clearly typeable

    • nullable string (?string in JS flow)
    • list of 'things' (.e.g. any[] in typescript)
    • side effect only function (None return type in mypy)

    As a result of missing types, this has to be repeated in the documentation, in vague human language.

  • yes, in elisp it's often easier to just inspect the object in question (e.g. in repl or the debugger) instead of thinking of it in terms of types
  • yes, you can add type checking (clojure things?), but I've never really seen it done except for defcustom

TODO [C] sort of hard to express… but basically elisp

CREATED: [2021-01-01]

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 elisp

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

-------------------------------------------- elisp

TODO [C] defaul error reporting sucks elisp

CREATED: [2021-01-01]

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 elisp

  • fuck poor standard library and need for cl-lib
    "buffers are a better abstraction than strings"?
    • hmm okay this has a point, I have to think about it.
      I guess it's true to some extent, but sometimes I do want to manipulate strings to make the code more pure
  • fuck lack of proper lexical binding
    file-local variable
    also not sure what was the last time it bothered me… maybe some deafults changed?
  • fuck lack of currying
    currying : dash.el it things, also partial/rpartial
    kind of cool actually that it's implemented xxx (on the other hand would be possible in python too? with a special object or something)
  • fuck parentheses (admit this one is subjective)
    multiple types of parens makes it much better (like in clojure)
    but unlikely it's something solvable within elisp

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

CREATED: [2019-10-18]

[D] [2019-10-20] Output Functions - GNU Emacs Lisp Reference Manual elisplisp

[D] why elisp sucks: buffer-size elisp

CREATED: [2019-10-19]

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


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

whereas buffer-filename takes optional argument

[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. elisp

[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. elisp

-------------------------------------------- elisp

[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? elisp

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

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

CREATED: [2019-10-19]

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

CREATED: [2019-10-19]

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

CREATED: [2019-10-19]

TODO lisp: discourages intermediate variables elisplisp

CREATED: [2021-01-01]

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' правильно интерпретирует

[C] good parts elisp

TODO good: parinfer sometimes is quite nice elisp

CREATED: [2021-01-01]

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

TODO good parts elisptoblog

CREATED: [2021-01-01]


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

CREATED: [2021-01-06]

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

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

CREATED: [2020-01-03]

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

[D] appreciation why is something good is hard, you don't notice it as easy as bad things elisp

CREATED: [2019-12-07]

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.

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

CREATED: [2020-01-03]

CANCEL [C] "How do we kill Elisp?" elisptoblog

CREATED: [2020-04-12]

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

CREATED: [2021-01-26]

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

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

CREATED: [2020-12-06]

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

TODO [D] try finding out how to take nth character of a string elispelisp_sucks

CREATED: [2021-02-06]

[C] [2021-02-06] elisp - How to determine if the current character is a letter - Emacs Stack Exchange elispelisp_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.

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

CREATED: [2021-03-15]

TODO [A] Structure as problem– solution elisp

CREATED: [2021-03-07]

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

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

CREATED: [2021-03-15]

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)

Jump to search, settings & sitemap