

Elisp Cheet Sheet
source link: https://www.tuicool.com/articles/hit/BFBZRvi
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

ElispCheatSheet
Quick reference to the core language of Emacs —Editor MACroS.
( Much Emacs Lisp was utilised in making my blog https://alhassy.github.io )
The listing sheet, as PDF, can be found here , while below is an unruly html rendition.
This reference sheet is built around the system https://github.com/alhassy/CheatSheet .
Table of Contents
Everything is a list!
-
To find out more about
name
execute(describe-symbol 'name)
!-
After the closing parens invoke
C-x C-e
to evaluate.
-
After the closing parens invoke
-
To find out more about a key press, execute
C-h k
then the key press. -
To find out more about the current mode you're in, execute
C-h m
ordescribe-mode
. Essentially a comprehensive yet terse reference is provided.
Functions
-
Function invocation:
(f x₀ x₁ … xₙ)
. E.g.,(+ 3 4)
or(message "hello")
.-
After the closing parens invoke
C-x C-e
to execute them. -
Warning! Arguments are evaluated before the function is executed.
-
Only prefix invocations means we can use
-,+,*
in names since(f+*- a b)
is parsed as applying functionf+*-
to argumentsa, b
.E.g.,
(1+ 42) → 43
using function named1+
–the ‘successor function’.
-
-
Function definition:
;; “de”fine “fun”ctions (defun my-fun (arg₀ arg₁ … argₖ) ;; header, signature "This functions performs task …" ;; documentation, optional …sequence of instructions to perform… ;; body )
- The return value of the function is the result of the last expression executed.
- The documentation string may indicate the return type, among other things.
-
Anonymous functions:
(lambda (arg₀ … argₖ) bodyHere)
.;; make and immediately invoke ((lambda (x y) (message (format "x, y ≈ %s, %s" x y))) 1 2) ;; make then way later invoke (setq my-func (lambda (x y) (message (format "x, y ≈ %s, %s" x y)))) (funcall my-func 1 2) ;; (my-func 1 2) ;; invalid!
The last one is invalid since
(f x0 … xk)
is only meaningful for functionsf
formed usingdefun
. More honestly, Elisp has distinct namespaces for functions and variables.Indeed,
(defun f (x₀ … xₖ) body) ≈ (fset 'f (lambda (x₀ … xₖ) body))
.-
Using
fset
, with quoted name, does not require usingfuncall
.
-
Using
-
Recursion and IO:
(defun sum (n) (if (<= n 0) 0 (+ n (sum (- n 1)))))
-
Now
(sum 100) → 5050
.
-
Now
-
IO:
(defun make-sum (n) (interactive "n") (message-box (format "%s" (sum n))))
-
The
interactive
option means the value ofn
is queried to the user; e.g., enter 100 after executing(execute-extended-command "" "make-sum")
orM-x make-sum
. -
In general
interactive
may take no arguments. The benefit is that the function can be executed usingM-x
, and is then referred to as an interactive function.
-
The
\newpage
Variables
-
Global Variables, Create & Update:
(setq name value)
.-
Generally:
(setq name₀ value₀ ⋯ nameₖ valueₖ)
.
Use
devfar
for global variables since it permits a documentation string –but updates must be performed withsetq. E.g., ~(defvar my-x 14 "my cool thing")
. -
Generally:
-
Local Scope:
(let ((name₀ val₀) … (nameₖ valₖ)) bodyBlock)
.let* let
-
Elisp is dynamically scoped: The caller's stack is accessible by default!
(defun woah () "If any caller has a local ‘work’, they're in for a nasty bug from me! Moreover, they better have ‘a’ defined in scope!" (setq work (* a 111))) ;; Benefit: Variable-based scoped configuration. (defun add-one (x) "Just adding one to input, innocently calling library method ‘woah’." (let ((work (+ 1 x)) (a 6)) (woah) ;; May change ‘work’ or access ‘a’! work ) ) ;; (add-one 2) ⇒ 666
Useful for loops, among other things:
C Elisp `x += y` `(incf x y)` `x--` `(decf x)` `x++` `(incf x)`-
Quotes:
'x
refers to the name rather than the value ofx
.-
This is superficially similar to pointers:
Given
int *x = …
,x
is the name (address) whereas*x
is the value. - The quote simply forbids evaluation; it means take it literally as you see it rather than looking up the definition and evaluating.
-
Note:
'x ≈ (quote x)
.
Akin to English, quoting a word refers to the word and not what it denotes.
( This lets us treat code as data ! E.g.,
'(+ 1 2)
evaluates to(+ 1 2)
, a function call, not the value3
! Another example,*
is code but'*
is data, and so(funcall '* 2 4)
yields 8. ) -
This is superficially similar to pointers:
Given
-
Atoms are the simplest objects in Elisp: They evaluate to themselves.
-
E.g.,
5, "a", 2.78, 'hello
, lambda's form function literals in that, e.g.,(lambda (x) x)
evaluates to itself.
-
E.g.,
\room
Elisp expressions are either atoms or function application –nothing else!
\newpage
Block of Code
Use the progn
function to treat multiple expressions as a single expression. E.g.,
(progn (message "hello") (setq x (if (< 2 3) 'two-less-than-3)) (sleep-for 0 500) (message (format "%s" x)) (sleep-for 0 500) 23 ;; Explicit return value )
This' like curly-braces in C or Java. The difference is that the last expression is considered the ‘return value’ of the block.
Herein, a ‘block’ is a number of sequential expressions which needn't be wrapped with a progn
form.
-
Lazy conjunction and disjunction:
-
Perform multiple statements but stop when any of them fails, returns
nil
:(and s₀ s₁ … sₖ)
.- Maybe monad!
-
Perform multiple statements until one of them succeeds, returns non-
nil
:(or s₀ s₁ … sₖ)
.
We can coerce a statement
sᵢ
to returning non-nil
as so: (progn sᵢ t)
. Likewise, coerce failure by(progn sᵢ nil)
. -
Perform multiple statements but stop when any of them fails, returns
-
Jumps, Control-flow transfer: Perform multiple statements and decide when and where you would like to stop.
-
(catch 'my-jump bodyBlock)
where the body may contain(throw 'my-jump returnValue)
;
the value of the catch/throw is then
returnValue
.-
Useful for when the
bodyBlock
is, say, a loop. Then we may have multiplecatch
's with different labels according to the nesting of loops.-
Possibly informatively named throw symbol is
'break
.
-
Possibly informatively named throw symbol is
-
Using name
'continue
for the throw symbol and having such a catch/throw as the body of a loop gives the impression of continue-statements from Java. -
Using name
'return
for the throw symbol and having such a catch/throw as the body of a function definition gives the impression of, possibly multiple, return-statements from Java –as well as ‘early exits’. -
Simple law:
(catch 'it s₀ s₁ … sₖ (throw 'it r) sₖ₊₁ ⋯ sₖ₊ₙ) ≈ (progn s₀ s₁ ⋯ sₖ r)
.-
Provided the
sᵢ
are simple function application forms.
-
Provided the
-
List Manipulation
-
Produce a syntactic, un-evaluated list, we use the single quote:
'(1 2 3)
. -
Construction:
(cons 'x₀ '(x₁ … xₖ)) → (x₀ x₁ … xₖ)
. -
Head, or contents of the address part of the register :
(car '(x₀ x₁ … xₖ)) → x₀
. -
Tail, or contents of the decrement part of the register :
(cdr '(x₀ x₁ … xₖ)) → (x₁ … xₖ)
. -
Deletion:
(delete e xs)
yieldsxs
with all instance ofe
removed.-
E.g.,
(delete 1 '(2 1 3 4 1)) → '(2 3 4)
.
-
E.g.,
E.g., (cons 1 (cons "a" (cons 'nice nil))) ≈ (list 1 "a" 'nice) ≈ '(1 "a" nice)
.
\room
Since variables refer to literals and functions have lambdas as literals, we
can produce forms that take functions as arguments. E.g., the standard mapcar
may be construed:
(defun my-mapcar (f xs) (if (null xs) xs (cons (funcall f (car xs)) (my-mapcar f (cdr xs))) ) ) (my-mapcar (lambda (x) (* 2 x)) '(0 1 2 3 4 5)) ;; ⇒ (0 2 4 6 8 10) (my-mapcar 'upcase '("a" "b" "cat")) ;; ⇒ ("A" "B" "CAT") (describe-symbol 'remove-if-not) ;; “filter” ;-)
Conditionals
-
Booleans:
nil
, the empty list()
, is considered false , all else is true .-
Note:
nil ≈ () ≈ '() ≈ 'nil
. -
(Deep structural) equality:
(equal x y)
. -
Comparisons: As expected; e.g.,
(<= x y)
denotes x ≤ y .
-
Note:
-
(if condition thenExpr optionalElseBlock)
-
Note:
(if x y) ≈ (if x y nil)
; better:(when c thenBlock) ≈ (if c (progn thenBlock))
. - Note the else-clause is a ‘block’: Everything after the then-clause is considered to be part of it.
-
Note:
-
Avoid nested if-then-else clauses by using a
cond
statement –a generalisation of switch statements.(cond (test₀ actionBlock₀) (test₁ actionBlock₁) … (t ;; optional defaultActionBlock))
Sequentially evaluate the predicates
testᵢ
and perform only the action of the first true test; yieldnil
when no tests are true. -
Make choices by comparing against only numbers or symbols –e.g., not strings!– with less clutter by using
case
:(case 'boberto ('bob 3) ('rob 9) ('bobert 9001) (otherwise "You're a stranger!"))
With case you can use either
t
orotherwise
for the default case, but it must come last.
\vfill
Exception Handling
We can attempt a dangerous clause and catch a possible exceptional case
–below we do not do so via nil
– for which we have an associated handler.
(condition-case nil attemptClause (error recoveryBody)) (ignore-errors attemptBody) ≈ (condition-case nil (progn attemptBody) (error nil)) (ignore-errors (+ 1 "nope")) ;; ⇒ nil
Loops
Sum the first 10
numbers:
(let ((n 100) (i 0) (sum 0)) (while (<= i n) (setq sum (+ sum i)) (setq i (+ i 1)) ) (message (number-to-string sum)) )
Essentially a for-loop:
(dotimes (x ;; refers to current iteration, initally 0 n ;; total number of iterations ret ;; optional: return value of the loop ) …body here, maybe mentioning x… ) ;; E.g., sum of first n numbers (let ((sum 0) (n 100)) (dotimes (i (1+ n) sum) (setq sum (+ sum i))))
A for-each loop: Iterate through a list.
Like dotimes
, the final item is the expression value at the end of the loop.
(dolist (elem '("a" 23 'woah-there) nil) (message (format "%s" elem)) (sleep-for 0 500) )
(describe-symbol 'sleep-for)
;-)
\newpage Example of Above Constructs
(defun my/cool-function (N D) "Sum the numbers 0..N that are not divisible by D" (catch 'return (when (< N 0) (throw 'return 0)) ;; early exit (let ((counter 0) (sum 0)) (catch 'break (while 'true (catch 'continue (incf counter) (cond ((equal counter N) (throw 'break sum)) ((zerop (% counter D)) (throw 'continue nil)) ('otherwise (incf sum counter)) ))))))) (my/cool-function 100 3) ;; ⇒ 3267 (my/cool-function 100 5) ;; ⇒ 4000 (my/cool-function -100 7) ;; ⇒ 0
Note that we could have had a final redundant throw 'return
:
Redundant since the final expression in a block is its return value.
\room
The special loop
constructs provide immensely many options to form
nearly any kind of imperative loop. E.g., Python-style ‘downfrom’ for-loops
and Java do-while loops. I personally prefer functional programming, so wont
look into this much.
Records
(defstruct X "Record with fields fᵢ having defaults dᵢ" (f₀ d₀) ⋯ (fₖ dₖ)) ;; Automatic constructor is “make-X” with keyword parameters for ;; initialising any subset of the fields! ;; Hence (expt 2 (1+ k)) kinds of possible constructor combinations! (make-X :f₀ val₀ :f₁ val₁ ⋯ :fₖ valₖ) ;; Any, or all, fᵢ may be omitted ;; Automatic runtime predicate for the new type. (X-p (make-X)) ;; ⇒ true (X-p 'nope) ;; ⇒ nil ;; Field accessors “X-fᵢ” take an X record and yield its value. ;; Field update: (setf (X-fᵢ x) valᵢ) (defstruct book title (year 0)) (setq ladm (make-book :title "Logical Approach to Discrete Math" :year 1993)) (book-title ladm) ;; ⇒ "Logical Approach to Discrete Math" (setf (book-title ladm) "LADM") (book-title ladm) ;; ⇒ "LADM"
Macros
- Sometimes we don't want eager evaluation; i.e., we do not want to recursively evaluate arguments before running a function.
- Macros let us manipulate a program's abstract syntax tree, usually by delaying some computations –easy since Elisp lets us treat code as data.
\room (e₀ e₁ ⋯ eₖ)
is known as a quasi-quote
: It produces syntactic data like quote
but allows computations to occur –any expression prefixed with a comma as in ,e₃
–
thereby eagerly evaluating some and delaying evaluation of others.
(defun my/lazy-or (this that) (if this t that)) (my/lazy-or (print "yup") (print "nope")) ;; evaluates & prints both clauses! (my/lazy-or t (/ 2 0)) ;; second clause runs needlessly, causing an error. ;; Delay argument evaluation using defmacro (defmacro my/lazy-or-2 (this that) `(if ,this t ,that)) (my/lazy-or-2 (print "yup") (print "nope")) ;; just "yup" ;-) (my/lazy-or-2 t (/ 2 0)) ;; second clause not evaluated ;; What code is generated by our macro? (macroexpand '(my/lazy-or-2 t (/ 2 0))) ;; ⇒ (if t t (/2 0))
We've added new syntax to Elisp!
\room
The above ‘equations’ can be checked by running macroexpand
; \newline e.g., (when c s₀ ⋯ sₙ) ≈ (if c (progn s₀ ⋯ sₙ) nil)
holds since
(macroexpand '(when c s₀ ⋯ sₙ)) ;; ⇒ (if c (progn s₀ ⋯ sₙ))
Woah!
\newpage
Hooks
- We can ‘hook’ methods to run at particular events.
- Hooks are lists of functions that are, for example, run when a mode is initialised.
E.g.,
let's add the go
function to the list of functions when a buffer
is initialised with org-mode.
(describe-symbol 'org-mode-hook) (defun go () (message-box "It worked!")) (add-hook 'org-mode-hook 'go) ≈ (add-hook 'org-mode-hook '(lambda () (message-box "It worked!"))) ≈ (add-to-list 'org-mode-hook 'go) ;; Now execute: (revert-buffer) to observe “go” being executed. ;; Later remove this silly function from the list: (remove-hook 'org-mode-hook 'go)
-
The
'after-init-hook
event will run functions after the rest of the init-file has finished loading.
\vfill
Reads
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK