Notes from reading Emacs Lisp Reference Manual.

1. Intro

1.1. Why the heck did I start reading this?

Well because RTFM is one of the best ways (if not the way) to actually really grasp any languages and I've been putting it off for too long since I started using Emacs. Secondly, I'm maintaining my own Emacs config and it's becoming really hard to maintain because of debugging issues I had. Finally, I was again reminded by this talk that one needs to go through the manual to get good at elisp programming.

So I started reading the manual and documenting notes here. I don't intend to run every example code snippet but pick some functions that I think are important in general and to myself. However I do try to copy and paste all functions mentioned in the manual so that I can grep this file for things I need instead of Googling randomly.

2. Lisp definitions and types

  • A Lisp expression that you can evaluate is called a “form”.
  • A “symbol” in GNU Emacs Lisp is an object with a name.
  • A symbol whose name starts with a colon (‘:’) is called a “keyword symbol”.
  • A “sequence” is a Lisp object that represents an ordered set of elements. There are two kinds of sequence in Emacs Lisp: “lists” and “arrays”.
  • A “cons cell” is an object that consists of two slots, called the CAR slot and the CDR slot.
    • Each slot can “hold” any Lisp object.
    • We also say that the CAR of this cons cell is whatever object its CAR slot currently holds, and likewise for the CDR.
    • CDR is pronounced “could-er”.
  • An “association list” or “alist” is a specially-constructed list whose elements are cons cells.
  • An “array” is composed of an arbitrary number of slots for holding or referring to other Lisp objects, arranged in a contiguous block of memory. (approx. O(1) access time).
    • Emacs defines four types of array: strings, vectors, bool-vectors, and char-tables.
    • A “vector” is a one-dimensional array of elements of any type. It takes a constant amount of time to access any element of a vector.
    • A “char-table” is a one-dimensional array of elements of any type, indexed by character codes.
    • A “bool-vector” is a one-dimensional array whose elements must be ‘t’ or ‘nil’.
      • The printed representation of a bool-vector is like a string, except that it begins with ‘#&’ followed by the length.
    • A hash table is a very fast kind of lookup table, somewhat like an alist in that it maps keys to corresponding values, but much faster.
  • A “Lisp macro” is a user-defined construct that extends the Lisp language.
  • A “primitive function” is a function callable from Lisp but written in the C programming language.
    • Primitive functions are also called “subrs” or “built-in functions”.
    • Most primitive functions evaluate all their arguments when they are called. A primitive function that does not evaluate all its arguments is called a “special form”.
  • A “record” is much like a ‘vector’. However, the first element is used to hold its type as returned by ‘type-of’. The purpose of records is to allow programmers to create objects with new types that are not built into Emacs.
  • An “autoload object” is a list whose first element is the symbol ‘autoload’.
  • A “finalizer object” helps Lisp code clean up after objects that are no longer needed.

   The names CAR and CDR derive from the history of Lisp. The original
Lisp implementation ran on an IBM 704 computer which divided words into
two parts, the address and the decrement; CAR was an instruction to
extract the contents of the address part of a register, and CDR an
instruction to extract the contents of the decrement. By contrast, cons
cells are named for the function ‘cons’ that creates them, which in turn
was named for its purpose, the construction of cells.

(rose violet buttercup)
      ----------–— -----------–— --------------–—
     | car | cdr | | car | cdr | | car | cdr |
     | rose | o---–—>| violet | o---–—>| buttercup | nil |
     | | | | | | | | |
      ----------–— -----------–— --------------–—

((pine needles) oak maple)

      ---------–— ---------–— ---------–—
     | car | cdr | | car | cdr | | car | cdr |
     | o | o--–—>| oak | o--–—>| maple | nil |
     | | | | | | | | | |
      – | ----–— ---------–— ---------–—
         |
         |
         | ---------–— -----------–—
         | | car | cdr | | car | cdr |
          -–—>| pine | o--–—>| needles | nil |
                 | | | | | |
                  ---------–— -----------–—

alist

((rose . red) (lily . white) (buttercup . yellow))
      ----------–— -----------–— --------------–—
     | car | cdr | | car | cdr | | car | cdr |
     | rose | o---–—>| lily | o---–—>| buttercup | nil |
     | red | | | white | | | yellow | |
      ----------–— -----------–— --------------–—

[1 "two" (three)]      ; A vector of three elements.

3. Editing types

  • A “marker” denotes a position in a specific buffer.
  • A “window” describes the portion of the terminal screen that Emacs uses to display a buffer. Every window has one associated buffer, whose contents appear in the window. By contrast, a given buffer may appear in one window, no window, or several windows.
  • A “frame” is a screen area that contains one or more Emacs windows. We also use the term “frame” to refer to the Lisp object that Emacs uses to refer to the screen area.
  • A process is a Lisp object that designates a subprocess created by the Emacs process.
    • An Emacs subprocess takes textual input from Emacs and returns textual output to Emacs for further manipulation. Emacs can also send signals to the subprocess.
    • (process-list)
  • A “thread” in Emacs represents a separate thread of Emacs Lisp execution. It runs its own Lisp program, has its own current buffer, and can have subprocesses locked to it, i.e. subprocesses whose output only this thread can accept.
    • (all-threads)
  • A “mutex” is an exclusive lock that threads can own and disown, in order to synchronize between them.
  • A “condition variable” is a device for a more complex thread synchronization than the one supported by a mutex. A thread can wait on a condition variable, to be woken up when some other thread notifies the condition.
  • A “stream” is an object that can be used as a source or sink for characters—either to supply characters for input or to accept them as output.
  • A “keymap” maps keys typed by the user to commands. This mapping controls how the user’s command input is executed. A keymap is actually a list whose CAR is the symbol ‘keymap’.
  • An “overlay” specifies properties that apply to a part of a buffer. Each overlay applies to a specified range of the buffer, and contains a property list (a list whose elements are alternating property names and values). Overlay properties are used to present parts of the buffer temporarily in a different display style. Overlays have no read syntax, and print in hash notation, giving the buffer name and range of positions.
  • A “font” specifies how to display text on a graphical terminal.
    • font objects
    • font specs
    • font entities

4. Type checking (predicates)

(setq list nil)
(defun add-on (x)
  (cond ((symbolp x)
         ;; If X is a symbol, put it on LIST.
         (setq list (cons x list))) 
        ((listp x)
         ;; If X is a list, add its elements to LIST.
         (setq list (append x list))) 
        (t
         ;; We handle only symbols and lists.
         (error 
          "Invalid argument %s in add-on"
          x))))
(add-on 'a)

4.1. list of type predicates

Put this here as a quick reference for grepping.

‘atom’
     *Note atom: List-related Predicates.

‘arrayp’
     *Note arrayp: Array Functions.

‘bignump’
     *Note floatp: Predicates on Numbers.

‘bool-vector-p’
     *Note bool-vector-p: Bool-Vectors.

‘booleanp’
     *Note booleanp: nil and t.

‘bufferp’
     *Note bufferp: Buffer Basics.

‘byte-code-function-p’
     *Note byte-code-function-p: Byte-Code Type.

‘case-table-p’
     *Note case-table-p: Case Tables.

‘char-or-string-p’
     *Note char-or-string-p: Predicates for Strings.

‘char-table-p’
     *Note char-table-p: Char-Tables.

‘commandp’
     *Note commandp: Interactive Call.

‘condition-variable-p’
     *Note condition-variable-p: Condition Variables.

‘consp’
     *Note consp: List-related Predicates.

‘custom-variable-p’
     *Note custom-variable-p: Variable Definitions.

‘fixnump’
     *Note floatp: Predicates on Numbers.

‘floatp’
     *Note floatp: Predicates on Numbers.

‘fontp’
     *Note Low-Level Font::.

‘frame-configuration-p’
     *Note frame-configuration-p: Frame Configurations.

‘frame-live-p’
     *Note frame-live-p: Deleting Frames.

‘framep’
     *Note framep: Frames.

‘functionp’
     *Note functionp: Functions.

‘hash-table-p’
     *Note hash-table-p: Other Hash.

‘integer-or-marker-p’
     *Note integer-or-marker-p: Predicates on Markers.

‘integerp’
     *Note integerp: Predicates on Numbers.

‘keymapp’
     *Note keymapp: Creating Keymaps.

‘keywordp’
     *Note Constant Variables::.

‘listp’
     *Note listp: List-related Predicates.

‘markerp’
     *Note markerp: Predicates on Markers.

‘mutexp’
     *Note mutexp: Mutexes.

‘nlistp’
     *Note nlistp: List-related Predicates.

‘number-or-marker-p’
     *Note number-or-marker-p: Predicates on Markers.

‘numberp’
     *Note numberp: Predicates on Numbers.

‘overlayp’
     *Note overlayp: Overlays.

‘processp’
     *Note processp: Processes.

‘recordp’
     *Note recordp: Record Type.

‘sequencep’
     *Note sequencep: Sequence Functions.

‘string-or-null-p’
     *Note string-or-null-p: Predicates for Strings.

‘stringp’
     *Note stringp: Predicates for Strings.

‘subrp’
     *Note subrp: Function Cells.

‘symbolp’
     *Note symbolp: Symbols.

‘syntax-table-p’
     *Note syntax-table-p: Syntax Tables.

‘threadp’
     *Note threadp: Basic Thread Functions.

‘vectorp’
     *Note vectorp: Vectors.

‘wholenump’
     *Note wholenump: Predicates on Numbers.

‘window-configuration-p’
     *Note window-configuration-p: Window Configurations.

‘window-live-p’
     *Note window-live-p: Deleting Windows.

‘windowp’
     *Note windowp: Basic Windows.

5. Equality predicates

5.1. eq (deep compare)

(eq 'foo 'foo) ;; t
(eq ?A ?A) ;; t
(eq 3.0 3.0) ;; t or nil Equal floats may or may not be the same object.
(eq (make-string 3 ?A) (make-string 3 ?A)) ;; nil because these are two different objects
(eq "asdf" "asdf") ;; t or nil Equal string constants or may not be the same object.

(eq '(1 (2 (3))) '(1 (2 (3)))) ;; nil

(setq foo '(1 (2 (3))))
(eq foo foo) ;; t
(eq foo '(1 (2 (3)))) ;; nil
(eq (point-marker) (point-marker)) ;; nil

(eq (make-symbol "foo") 'foo) ;; nil

Odd one with make-symbol and intern (see also: elisp make-symbol vs intern).

(eq (make-symbol "foo") 'foo) ;; nil
(eq (intern "foo") 'foo) ;; t

5.2. equal (shallow compare)

(equal 'foo 'foo) ;; t
(equal "asdf" "asdf") ;; t
(equal (point-marker) (point-marker)) ;; t
(equal (make-symbol "foo") 'foo) ;; nil
(equal (intern "foo") 'foo) ;; t
(equal "asdf" "ASDF") ;; nil. equal is case-sensitive

5.3. equal-including-properties to test

This function behaves like ‘equal’ in all cases but also requires
that for two strings to be equal, they have the same text
properties.

(equal "asdf" (propertize "asdf" 'asdf t))

(equal-including-properties "asdf"
                            (propertize "asdf" 'asdf t))

6. Mutability

(aset)

A mutable object stops being mutable if it is part of an expression that is evaluated. For example:

(let* ((x (list 0.5))
           (y (eval (list 'quote x))))
  (setcar x 1.5) ;; the program should not do this.
  (car x)
  )

If a program attempts to change objects that should not be changed, the resulting behavior is undefined: the Lisp interpreter might signal an error, or it might crash or behave unpredictably in other ways.

7. Numbers

7.1. Integer

Integer representations:

1  ;; The integer 1.
1. ;; The integer 1.
+1 ;; Also the integer 1.
-1 ;; The integer −1.
0  ;; The integer 0.
-0 ;; The integer 0.

The syntax for integers in bases other than 10 consists of ‘#’ followed by a radix indication followed by one or more digits. The radix indications are ‘b’ for binary, ‘o’ for octal, ‘x’ for hex, and ‘RADIXr’ for radix RADIX. Thus, ‘#bINTEGER’ reads INTEGER in binary, and ‘#RADIXrINTEGER’ reads INTEGER in radix RADIX. Allowed values of RADIX run from 2 to 36, and allowed digits are the first RADIX characters taken from ‘0’–‘9’, ‘A’–‘Z’. Letter case is ignored and there is no initial sign or final period. For example:

(message (format "%s" #b101100))        ⇒ 44
#o54            ⇒ 44
#x2c            ⇒ 44
#24r1k  ⇒ 44

Some useful variables.

– Variable: most-positive-fixnum
    The value of this variable is the greatest “small” integer that
    Emacs Lisp can handle. Typical values are 2**29 − 1 on 32-bit and
    2**61 − 1 on 64-bit platforms.

– Variable: most-negative-fixnum
    The value of this variable is the numerically least “small” integer
    that Emacs Lisp can handle. It is negative. Typical values are
    −2**29 on 32-bit and −2**61 on 64-bit platforms.

– Variable: integer-width
    The value of this variable is a nonnegative integer that controls
    whether Emacs signals a range error when a large integer would be
    calculated. Integers with absolute values less than 2**N, where N
    is this variable’s value, do not signal a range error. Attempts to
    create larger integers typically signal a range error, although
    there might be no signal if a larger integer can be created
    cheaply. Setting this variable to a large number can be costly if
    a computation creates huge integers.

7.2. Floating-Point number

(= 0.0 0) ;; t
(= -0.0 0) ;; t
(/ 0.0 0.0) ;; -0.0e+NaN
(setq x -0.0e+NaN)
(setq y -0.0e+NaN)
(= x y) ;; nil
(equal x y) ;; t
(eq x y) ;; nil

Useful functions

– Function: isnan x
    This predicate returns ‘t’ if its floating-point argument is a NaN,
    ‘nil’ otherwise.

– Function: frexp x
    This function returns a cons cell ‘(S . E)’, where S and E are
    respectively the significand and exponent of the floating-point
    number X.

    If X is finite, then S is a floating-point number between 0.5
    (inclusive) and 1.0 (exclusive), E is an integer, and X = S * 2**E.
    If X is zero or infinity, then S is the same as X. If X is a NaN,
    then S is also a NaN. If X is zero, then E is 0.

– Function: ldexp s e
    Given a numeric significand S and an integer exponent E, this
    function returns the floating point number S * 2**E.

– Function: copysign x1 x2
    This function copies the sign of X2 to the value of X1, and returns
    the result. X1 and X2 must be floating point.

– Function: logb x
    This function returns the binary exponent of X. More precisely, if
    X is finite and nonzero, the value is the logarithm base 2 of |x|,
    rounded down to an integer. If X is zero or infinite, the value is
    infinity; if X is a NaN, the value is a NaN.

  (logb 10)
       ⇒ 3
  (logb 10.0e20)
       ⇒ 69
  (logb 0)
       ⇒ -1.0e+INF

7.3. Type Predicates for Numbers

– Function: bignump object
    This predicate tests whether its argument is a large integer, and
    returns ‘t’ if so, ‘nil’ otherwise. Unlike small integers, large
    integers can be ‘=’ or ‘eql’ even if they are not ‘eq’.

– Function: fixnump object
    This predicate tests whether its argument is a small integer, and
    returns ‘t’ if so, ‘nil’ otherwise. Small integers can be compared
    with ‘eq’.

– Function: floatp object
    This predicate tests whether its argument is floating point and
    returns ‘t’ if so, ‘nil’ otherwise.

– Function: integerp object
    This predicate tests whether its argument is an integer, and
    returns ‘t’ if so, ‘nil’ otherwise.

– Function: numberp object
    This predicate tests whether its argument is a number (either
    integer or floating point), and returns ‘t’ if so, ‘nil’ otherwise.

– Function: natnump object
    This predicate (whose name comes from the phrase “natural number”)
    tests to see whether its argument is a nonnegative integer, and
    returns ‘t’ if so, ‘nil’ otherwise. 0 is considered non-negative.

    ‘wholenump’ is a synonym for ‘natnump’.

– Function: zerop number
    This predicate tests whether its argument is zero, and returns ‘t’
    if so, ‘nil’ otherwise. The argument must be a number.

    ‘(zerop x)’ is equivalent to ‘(= x 0)’.

7.4. Comparison of Numbers

Because floating-point arithmetic is not exact, it is often a bad idea to check for equality of floating-point values. Usually it is better to test for approximate equality. Here’s a function to do this:

(defvar fuzz-factor 1.0e-6)
(defun approx-equal (x y)
  (or (= x y) 
          (< (/ (abs (- x y)) 
                        (max (abs x) 
                                 (abs y))) fuzz-factor)))

Useful functions.

– Function: = number-or-marker &rest number-or-markers
    This function tests whether all its arguments are numerically
    equal, and returns ‘t’ if so, ‘nil’ otherwise.

– Function: eql value1 value2
    This function acts like ‘eq’ except when both arguments are
    numbers. It compares numbers by type and numeric value, so that
    ‘(eql 1.0 1)’ returns ‘nil’, but ‘(eql 1.0 1.0)’ and ‘(eql 1 1)’
    both return ‘t’. This can be used to compare large integers as
    well as small ones.

– Function: /= number-or-marker1 number-or-marker2
    This function tests whether its arguments are numerically equal,
    and returns ‘t’ if they are not, and ‘nil’ if they are.

– Function: < number-or-marker &rest number-or-markers
    This function tests whether each argument is strictly less than the
    following argument. It returns ‘t’ if so, ‘nil’ otherwise.

– Function: <= number-or-marker &rest number-or-markers
    This function tests whether each argument is less than or equal to
    the following argument. It returns ‘t’ if so, ‘nil’ otherwise.

– Function: > number-or-marker &rest number-or-markers
    This function tests whether each argument is strictly greater than
    the following argument. It returns ‘t’ if so, ‘nil’ otherwise.

– Function: >= number-or-marker &rest number-or-markers
    This function tests whether each argument is greater than or equal
    to the following argument. It returns ‘t’ if so, ‘nil’ otherwise.

– Function: max number-or-marker &rest numbers-or-markers
    This function returns the largest of its arguments.

  (max 20)
       ⇒ 20
  (max 1 2.5)
       ⇒ 2.5
  (max 1 3 2.5)
       ⇒ 3

– Function: min number-or-marker &rest numbers-or-markers
    This function returns the smallest of its arguments.

  (min -4 1)
       ⇒ -4

– Function: abs number
    This function returns the absolute value of NUMBER.

7.5. Numeric Conversions

To convert an integer to floating point, use the function ‘float’.

;; This returns NUMBER converted to floating point.  If NUMBER is
;; already floating point, ‘float’ returns it unchanged.
(float 1) ;; 1.0

There are four functions to convert floating-point numbers to integers; they differ in how they round. All accept an argument NUMBER and an optional argument DIVISOR. Both arguments may be integers or floating-point numbers. DIVISOR may also be ‘nil’. If DIVISOR is ‘nil’ or omitted, these functions convert NUMBER to an integer, or return it unchanged if it already is an integer. If DIVISOR is non-‘nil’, they divide NUMBER by DIVISOR and convert the result to an integer. If DIVISOR is zero (whether integer or floating point), Emacs signals an ‘arith-error’ error.

(truncate 1.2) ;; 1
(truncate 7.2 3) ;; 2
(truncate -1.2) ;; -1
(floor 1.2) ;; 1
(floor -1.2) ;; -2
(ceiling 1.2) ;; 2
(ceiling -1.2) ;; -1
(round 1.2) ;; 1
(round -1.2) ;; -1
(round 7 3) ;; 2

7.6. Arithmetic Operations

Plus 1.

(1+ 1) ;; 2

Minus 1.

(1- 1) ;; 0
(+) ;; 0
(+ 1) ;; 1
(-) ;; 0
(- 10) ;; -10
(- 10 1) ;; 9
(*) ;; 1
(* 10) ;; 10
(* 10 2 2) ;; 40
(* 10 2 2.0) ;; 40.0
(/ 6 2) ;; 3
(/ 6 2.0) ;; 3.0
(/ 4) ;; 0

;; remainder
(% 10 2) ;; 0
(% 11 2) ;; 1
(% 11.0 2) ;; wrong-type-argument number-or-marker-p 11.0

(mod 9 4) ;; 1
(mod 9.0 4) ;; 1.0

7.7. (float) Rounding Operations

The functions ‘ffloor’, ‘fceiling’, ‘fround’, and ‘ftruncate’ take a
floating-point argument and return a floating-point result whose value
is a nearby integer. ‘ffloor’ returns the nearest integer below;
‘fceiling’, the nearest integer above; ‘ftruncate’, the nearest integer
in the direction towards zero; ‘fround’, the nearest integer.

 – Function: ffloor float
     This function rounds FLOAT to the next lower integral value, and
     returns that value as a floating-point number.

 – Function: fceiling float
     This function rounds FLOAT to the next higher integral value, and
     returns that value as a floating-point number.

 – Function: ftruncate float
     This function rounds FLOAT towards zero to an integral value, and
     returns that value as a floating-point number.

 – Function: fround float
     This function rounds FLOAT to the nearest integral value, and
     returns that value as a floating-point number. Rounding a value
     equidistant between two integers returns the even integer.


7.8. Bitwise Operations on Integers

Won't touch this here at the moment.

3.8 Bitwise Operations on Integers

7.9. Standard Math Functions

 – Function: sin arg
 – Function: cos arg
 – Function: tan arg
     These are the basic trigonometric functions, with argument ARG
     measured in radians.

 – Function: asin arg
     The value of ‘(asin ARG)’ is a number between −pi/2 and pi/2
     (inclusive) whose sine is ARG. If ARG is out of range (outside
     [−1, 1]), ‘asin’ returns a NaN.

 – Function: acos arg
     The value of ‘(acos ARG)’ is a number between 0 and pi (inclusive)
     whose cosine is ARG. If ARG is out of range (outside [−1, 1]),
     ‘acos’ returns a NaN.

 – Function: atan y &optional x
     The value of ‘(atan Y)’ is a number between −pi/2 and pi/2
     (exclusive) whose tangent is Y. If the optional second argument X
     is given, the value of ‘(atan y x)’ is the angle in radians between
     the vector ‘[X, Y]’ and the ‘X’ axis.

 – Function: exp arg
     This is the exponential function; it returns e to the power ARG.

 – Function: log arg &optional base
     This function returns the logarithm of ARG, with base BASE. If you
     don’t specify BASE, the natural base e is used. If ARG or BASE is
     negative, ‘log’ returns a NaN.

 – Function: expt x y
     This function returns X raised to power Y. If both arguments are
     integers and Y is nonnegative, the result is an integer; in this
     case, overflow signals an error, so watch out. If X is a finite
     negative number and Y is a finite non-integer, ‘expt’ returns a
     NaN.

 – Function: sqrt arg
     This returns the square root of ARG. If ARG is finite and less
     than zero, ‘sqrt’ returns a NaN.

   In addition, Emacs defines the following common mathematical
constants:

 – Variable: float-e
     The mathematical constant e (2.71828…).

 – Variable: float-pi
     The mathematical constant pi (3.14159…).

7.10. Random numbers

;; choose a seed based on the string contents
(random "")
;; If LIMIT is ‘t’, it means to choose a new seed as if Emacs were
;; restarting, typically from the system entropy.  On systems lacking
;; entropy pools, choose the seed from less-random volatile data such
;; as the current time.
(random t)

;; If LIMIT is a positive fixnum, the value is chosen to be
;; nonnegative and less than LIMIT.
(random 100)
;; Otherwise, the value might be any 
;; fixnum, i.e., any integer from ‘most-negative-fixnum’ through
;; most-positive-fixnum’.
(random -100)
;; so the following two have the same effect?
(random -100)
(random)

8. String and Character Basics

In Emacs Lisp, characters are simply integers; whether an integer is a character or not is determined only by how it is used.

(aref "abc" 0) ;; 97 (#o141, #x61, ?a)

8.1. Predicates for Strings

– Function: stringp object
    This function returns ‘t’ if OBJECT is a string, ‘nil’ otherwise.

– Function: string-or-null-p object
    This function returns ‘t’ if OBJECT is a string or ‘nil’. It
    returns ‘nil’ otherwise.

– Function: char-or-string-p object
    This function returns ‘t’ if OBJECT is a string or a character
    (i.e., an integer), ‘nil’ otherwise.

(char-or-string-p 97) ;; t, because this is character a
(char-or-string-p "a") ;; t

8.2. Creating Strings

List of useful functions.

– Function: make-string count character &optional multibyte
    This function returns a string made up of COUNT repetitions of
    CHARACTER. If COUNT is negative, an error is signaled.

  (make-string 5 ?x)
       ⇒ "xxxxx"
  (make-string 0 ?x)
       ⇒ ""

    Normally, if CHARACTER is an ASCII character, the result is a
    unibyte string. But if the optional argument MULTIBYTE is
    non-‘nil’, the function will produce a multibyte string instead.
    This is useful when you later need to concatenate the result with
    non-ASCII strings or replace some of its characters with non-ASCII
    characters.

    Other functions to compare with this one include ‘make-vector’
    (*note Vectors::) and ‘make-list’ (*note Building Lists::).

– Function: string &rest characters
    This returns a string containing the characters CHARACTERS.

  (string ?a ?b ?c)
       ⇒ "abc"

– Function: substring string &optional start end
    This function returns a new string which consists of those
    characters from STRING in the range from (and including) the
    character at the index START up to (but excluding) the character at
    the index END. The first character is at index zero. With one
    argument, this function just copies STRING.

  (substring "abcdefg" 0 3)
       ⇒ "abc"

    In the above example, the index for ‘a’ is 0, the index for ‘b’ is
    1, and the index for ‘c’ is 2. The index 3—which is the fourth
    character in the string—marks the character position up to which
    the substring is copied. Thus, ‘abc’ is copied from the string
    ‘"abcdefg"’.

    A negative number counts from the end of the string, so that −1
    signifies the index of the last character of the string. For
    example:

  (substring "abcdefg" -3 -1)
       ⇒ "ef"

    In this example, the index for ‘e’ is −3, the index for ‘f’ is −2,
    and the index for ‘g’ is −1. Therefore, ‘e’ and ‘f’ are included,
    and ‘g’ is excluded.

    When ‘nil’ is used for END, it stands for the length of the string.
    Thus,

  (substring "abcdefg" -3 nil)
       ⇒ "efg"

    Omitting the argument END is equivalent to specifying ‘nil’. It
    follows that ‘(substring STRING 0)’ returns a copy of all of
    STRING.

  (substring "abcdefg" 0)
       ⇒ "abcdefg"

    But we recommend ‘copy-sequence’ for this purpose (*note Sequence
    Functions::).

    If the characters copied from STRING have text properties, the
    properties are copied into the new string also. *Note Text
    Properties::.

    ‘substring’ also accepts a vector for the first argument. For
    example:

  (substring [a b (c) "d"] 1 3)
       ⇒ [b (c)]

    A ‘wrong-type-argument’ error is signaled if START is not an
    integer or if END is neither an integer nor ‘nil’. An
    ‘args-out-of-range’ error is signaled if START indicates a
    character following END, or if either integer is out of range for
    STRING.

    Contrast this function with ‘buffer-substring’ (*note Buffer
    Contents::), which returns a string containing a portion of the
    text in the current buffer. The beginning of a string is at index
    0, but the beginning of a buffer is at index 1.

– Function: substring-no-properties string &optional start end
    This works like ‘substring’ but discards all text properties from
    the value. Also, START may be omitted or ‘nil’, which is
    equivalent to 0. Thus, ‘(substring-no-properties STRING)’ returns
    a copy of STRING, with all text properties removed.

– Function: concat &rest sequences
    This function returns a string consisting of the characters in the
    arguments passed to it (along with their text properties, if any).
    The arguments may be strings, lists of numbers, or vectors of
    numbers; they are not themselves changed. If ‘concat’ receives no
    arguments, it returns an empty string.

  (concat "abc" "-def")
       ⇒ "abc-def"
  (concat "abc" (list 120 121) [122])
       ⇒ "abcxyz"
  ;; ‘nil’ is an empty sequence.
  (concat "abc" nil "-def")
       ⇒ "abc-def"
  (concat "The " "quick brown " "fox.")
       ⇒ "The quick brown fox."
  (concat)
       ⇒ ""

    This function does not always allocate a new string. Callers are
    advised not rely on the result being a new string nor on it being
    ‘eq’ to an existing string.

    In particular, mutating the returned value may inadvertently change
    another string, alter a constant string in the program, or even
    raise an error. To obtain a string that you can safely mutate, use
    ‘copy-sequence’ on the result.

    For information about other concatenation functions, see the
    description of ‘mapconcat’ in *note Mapping Functions::, ‘vconcat’
    in *note Vector Functions::, and ‘append’ in *note Building
    Lists::. For concatenating individual command-line arguments into
    a string to be used as a shell command, see *note
    combine-and-quote-strings: Shell Arguments.

– Function: split-string string &optional separators omit-nulls trim
    This function splits STRING into substrings based on the regular
    expression SEPARATORS (*note Regular Expressions::). Each match
    for SEPARATORS defines a splitting point; the substrings between
    splitting points are made into a list, which is returned.

    If SEPARATORS is ‘nil’ (or omitted), the default is the value of
    ‘split-string-default-separators’ and the function behaves as if
    OMIT-NULLS were ‘t’.

    If OMIT-NULLS is ‘nil’ (or omitted), the result contains null
    strings whenever there are two consecutive matches for SEPARATORS,
    or a match is adjacent to the beginning or end of STRING. If
    OMIT-NULLS is ‘t’, these null strings are omitted from the result.

    If the optional argument TRIM is non-‘nil’, it should be a regular
    expression to match text to trim from the beginning and end of each
    substring. If trimming makes the substring empty, it is treated as
    null.

    If you need to split a string into a list of individual
    command-line arguments suitable for ‘call-process’ or
    ‘start-process’, see *note split-string-and-unquote: Shell
    Arguments.

    Examples:

  (split-string " two words ")
       ⇒ ("two" "words")

    The result is not ‘("" "two" "words" "")’, which would rarely be
    useful. If you need such a result, use an explicit value for
    SEPARATORS:

  (split-string " two words "
         split-string-default-separators)
       ⇒ ("" "two" "words" "")

  (split-string "Soup is good food" "o")
       ⇒ ("S" "up is g" "" "d f" "" "d")
  (split-string "Soup is good food" "o" t)
       ⇒ ("S" "up is g" "d f" "d")
  (split-string "Soup is good food" "o+")
       ⇒ ("S" "up is g" "d f" "d")

    Empty matches do count, except that ‘split-string’ will not look
    for a final empty match when it already reached the end of the
    string using a non-empty match or when STRING is empty:

  (split-string "aooob" "o*")
       ⇒ ("" "a" "" "b" "")
  (split-string "ooaboo" "o*")
       ⇒ ("" "" "a" "b" "")
  (split-string "" "")
       ⇒ ("")

    However, when SEPARATORS can match the empty string, OMIT-NULLS is
    usually ‘t’, so that the subtleties in the three previous examples
    are rarely relevant:

  (split-string "Soup is good food" "o*" t)
       ⇒ ("S" "u" "p" " " "i" "s" " " "g" "d" " " "f" "d")
  (split-string "Nice doggy!" "" t)
       ⇒ ("N" "i" "c" "e" " " "d" "o" "g" "g" "y" "!")
  (split-string "" "" t)
       ⇒ nil

    Somewhat odd, but predictable, behavior can occur for certain
    “non-greedy” values of SEPARATORS that can prefer empty matches
    over non-empty matches. Again, such values rarely occur in
    practice:

  (split-string "ooo" "o*" t)
       ⇒ nil
  (split-string "ooo" "\\|o+" t)
       ⇒ ("o" "o" "o")

– Variable: split-string-default-separators
    The default value of SEPARATORS for ‘split-string’. Its usual
    value is ‘"[ \f\t\n\r\v]+"’.

8.3. Modifying strings

Useful functions.

(setq foo "abc")
(aset foo 1 ?c) ;; c
(message foo) ;; acc


(setq foo "abc")
(store-substring foo 0 "bb") ;; bbc
(message foo) ;; bbc


(setq foo "abc")
(clear-string foo) ;; nil

8.4. Comparison of Characters and Strings

char-equal.

(char-equal ?x ?x) ;; t
(char-equal ?x ?X) ;; t

;; should not ignore case
;; `case-fold-search`
(let ((case-fold-search nil))
  (char-equal ?x ?X)) ;; nil

string=

(string= "abc" "abc") ;; t

;; Case is always significant
;; regardless of `case-fold-search`
(string= "abc" "Abc") ;; nil


;; Symbols are also allowed as arguments, in which
;; case the symbol names are used.
(setq foo "abc")
(string= foo "abc") ;; t

;; create a symbol and assign "test" to its name cell.
(setq sym-test-random-var-name (make-symbol "test"))
(string= sym-test-random-var-name "test") ;; t

;; alias of string=
(string-equal "a" "a")

;; compares two strings using lexicographic order
(string< "abc" "abd") ;; t
(string< "abd" "abd") ;; nil
(string< "abe" "abd") ;; nil
(string< "be" "abd") ;; nil
;; alias for string<
(string-lessp "a" "b") ;; t
(string-greaterp "a" "b") ;; nil

(string-prefix-p "a" "ab") ;; t
(string-prefix-p "A" "ab") ;; nil
;; do not ignore case
(string-prefix-p "A" "ab" nil) ;; nil
(string-prefix-p "A" "ab" t) ;; t

(string-suffix-p "a" "ba") ;; t
(string-suffix-p "A" "ba") ;; nil
;; do not ignore case
(string-suffix-p "A" "ba" nil) ;; nil
(string-suffix-p "A" "ba" t) ;; t


;; “Levenshtein distance”
(string-distance "ab" "abc") ;; 1
(string-distance "Ab" "abc") ;; 2

Other functions.


 – Function: string-collate-lessp string1 string2 &optional locale
          ignore-case
     This function returns ‘t’ if STRING1 is less than STRING2 in
     collation order. A collation order is not only determined by the
     lexicographic order of the characters contained in STRING1 and
     STRING2, but also further rules about relations between these
     characters. Usually, it is defined by the LOCALE environment Emacs
     is running with.

     For example, punctuation and whitespace characters might be ignored
     for sorting (*note Sequence Functions::):

          (sort (list "11" "12" "1 1" "1 2" "1.1" "1.2") 'string-collate-lessp)
               ⇒ ("11" "1 1" "1.1" "12" "1 2" "1.2")

     This behavior is system-dependent; e.g., punctuation and whitespace
     are never ignored on Cygwin, regardless of locale.

     The optional argument LOCALE, a string, overrides the setting of
     your current locale identifier for collation. The value is system
     dependent; a LOCALE ‘"enUS.UTF-8"’ is applicable on POSIX systems,
     while it would be, e.g., ‘"enuUSA.1252"’ on MS-Windows systems.
     The LOCALE value of ‘"POSIX"’ or ‘"C"’ lets ‘string-collate-lessp’
     behave like ‘string-lessp’:

          (sort (list "11" "12" "1 1" "1 2" "1.1" "1.2")
                (lambda (s1 s2) (string-collate-lessp s1 s2 "POSIX")))
               ⇒ ("1 1" "1 2" "1.1" "1.2" "11" "12")

     If IGNORE-CASE is non-‘nil’, characters are converted to lower-case
     before comparing them.

     To emulate Unicode-compliant collation on MS-Windows systems, bind
     ‘w32-collate-ignore-punctuation’ to a non-‘nil’ value, since the
     codeset part of the locale cannot be ‘"UTF-8"’ on MS-Windows.

     If your system does not support a locale environment, this function
     behaves like ‘string-lessp’.

 – Function: string-version-lessp string1 string2
     This function compares strings lexicographically, except it treats
     sequences of numerical characters as if they comprised a base-ten
     number, and then compares the numbers. So ‘foo2.png’ is “smaller”
     than ‘foo12.png’ according to this predicate, even if ‘12’ is
     lexicographically “smaller” than ‘2’.


 – Function: compare-strings string1 start1 end1 string2 start2 end2
          &optional ignore-case
     This function compares a specified part of STRING1 with a specified
     part of STRING2. The specified part of STRING1 runs from index
     START1 (inclusive) up to index END1 (exclusive); ‘nil’ for START1
     means the start of the string, while ‘nil’ for END1 means the
     length of the string. Likewise, the specified part of STRING2 runs
     from index START2 up to index END2.

     The strings are compared by the numeric values of their characters.
     For instance, STR1 is considered less than STR2 if its first
     differing character has a smaller numeric value. If IGNORE-CASE is
     non-‘nil’, characters are converted to upper-case before comparing
     them. Unibyte strings are converted to multibyte for comparison
     (*note Text Representations::), so that a unibyte string and its
     conversion to multibyte are always regarded as equal.

     If the specified portions of the two strings match, the value is
     ‘t’. Otherwise, the value is an integer which indicates how many
     leading characters agree, and which string is less. Its absolute
     value is one plus the number of characters that agree at the
     beginning of the two strings. The sign is negative if STRING1 (or
     its specified portion) is less.
 – Function: assoc-string key alist &optional case-fold
     This function works like ‘assoc’, except that KEY must be a string
     or symbol, and comparison is done using ‘compare-strings’. Symbols
     are converted to strings before testing. If CASE-FOLD is
     non-‘nil’, KEY and the elements of ALIST are converted to
     upper-case before comparison. Unlike ‘assoc’, this function can
     also match elements of the alist that are strings or symbols rather
     than conses. In particular, ALIST can be a list of strings or
     symbols rather than an actual alist. *Note Association Lists::.

8.5. Conversion of Characters and Strings

(prin1-to-string (list 'a 'b 'c))
(number-to-string 256) ;; "256"
(string-to-number "25") ;; 25
(string-to-number "25f") ;; 25
(string-to-number "25 is a number") ;; 25
(string-to-number "f25") ;; 0

;; This function is semi-obsolete because the function
;; string’ is more general.
(char-to-string ?a) ;; "a"
(string ?a) ;; "a"

;; This function returns the first character in STRING.  This mostly
;; identical to ‘(aref string 0)’, except that it returns 0 if the
;; string is empty.
(string-to-char "abc") ;; 97

Other useful functions.

‘concat’
     This function converts a vector or a list into a string. *Note
     Creating Strings::.

‘vconcat’
     This function converts a string into a vector. *Note Vector
     Functions::.

‘append’
     This function converts a string into a list. *Note Building
     Lists::.

‘byte-to-string’
     This function converts a byte of character data into a unibyte
     string. *Note Converting Representations::.

8.6. Formatting Strings

Keeping this part here more for reference.

“Formatting” means constructing a string by substituting computed values
at various places in a constant string. This constant string controls
how the other values are printed, as well as where they appear; it is
called a “format string”.

   Formatting is often useful for computing messages to be displayed.
In fact, the functions ‘message’ and ‘error’ provide the same formatting
feature described here; they differ from ‘format-message’ only in how
they use the result of formatting.

 – Function: format string &rest objects
     This function returns a string equal to STRING, replacing any
     format specifications with encodings of the corresponding OBJECTS.
     The arguments OBJECTS are the computed values to be formatted.

     The characters in STRING, other than the format specifications, are
     copied directly into the output, including their text properties,
     if any. Any text properties of the format specifications are
     copied to the produced string representations of the argument
     OBJECTS.

     The output string need not be newly-allocated. For example, if ‘x’
     is the string ‘"foo"’, the expressions ‘(eq x (format x))’ and ‘(eq
     x (format "%s" x))’ might both yield ‘t’.

 – Function: format-message string &rest objects
     This function acts like ‘format’, except it also converts any grave
     accents (`) and apostrophes (') in STRING as per the value of
     ‘text-quoting-style’.

     Typically grave accent and apostrophe in the format translate to
     matching curved quotes, e.g., "Missing `%s'" might result in
     "Missing ‘foo’". *Note Text Quoting Style::, for how to influence
     or inhibit this translation.

   A format specification is a sequence of characters beginning with a
‘%’. Thus, if there is a ‘%d’ in STRING, the ‘format’ function replaces
it with the printed representation of one of the values to be formatted
(one of the arguments OBJECTS). For example:

     (format "The value of fill-column is %d." fill-column)
          ⇒ "The value of fill-column is 72."

   Since ‘format’ interprets ‘%’ characters as format specifications,
you should never pass an arbitrary string as the first argument. This
is particularly true when the string is generated by some Lisp code.
Unless the string is known to never include any ‘%’ characters, pass
‘"%s"’, described below, as the first argument, and the string as the
second, like this:

       (format "%s" ARBITRARY-STRING)

   Certain format specifications require values of particular types. If
you supply a value that doesn’t fit the requirements, an error is
signaled.

   Here is a table of valid format specifications:

‘%s’
     Replace the specification with the printed representation of the
     object, made without quoting (that is, using ‘princ’, not
     ‘prin1’—*note Output Functions::). Thus, strings are represented
     by their contents alone, with no ‘"’ characters, and symbols appear
     without ‘\’ characters.

     If the object is a string, its text properties are copied into the
     output. The text properties of the ‘%s’ itself are also copied,
     but those of the object take priority.

‘%S’
     Replace the specification with the printed representation of the
     object, made with quoting (that is, using ‘prin1’—*note Output
     Functions::). Thus, strings are enclosed in ‘"’ characters, and
     ‘\’ characters appear where necessary before special characters.

‘%o’
     Replace the specification with the base-eight representation of an
     integer. Negative integers are formatted in a platform-dependent
     way. The object can also be a floating-point number that is
     formatted as an integer, dropping any fraction.

‘%d’
     Replace the specification with the base-ten representation of a
     signed integer. The object can also be a floating-point number
     that is formatted as an integer, dropping any fraction.

‘%x’
‘%X’
     Replace the specification with the base-sixteen representation of
     an integer. Negative integers are formatted in a
     platform-dependent way. ‘%x’ uses lower case and ‘%X’ uses upper
     case. The object can also be a floating-point number that is
     formatted as an integer, dropping any fraction.

‘%c’
     Replace the specification with the character which is the value
     given.

‘%e’
     Replace the specification with the exponential notation for a
     floating-point number.

‘%f’
     Replace the specification with the decimal-point notation for a
     floating-point number.

‘%g’
     Replace the specification with notation for a floating-point
     number, using either exponential notation or decimal-point
     notation. The exponential notation is used if the exponent would
     be less than −4 or greater than or equal to the precision (default:
     6). By default, trailing zeros are removed from the fractional
     portion of the result and a decimal-point character appears only if
     it is followed by a digit.

‘%%’
     Replace the specification with a single ‘%’. This format
     specification is unusual in that its only form is plain ‘%%’ and
     that it does not use a value. For example, ‘(format "%% %d" 30)’
     returns ‘"% 30"’.

   Any other format character results in an ‘Invalid format operation’
error.

   Here are several examples, which assume the typical
‘text-quoting-style’ settings:

     (format "The octal value of %d is %o,
              and the hex value is %x." 18 18 18)
          ⇒ "The octal value of 18 is 22,
              and the hex value is 12."

     (format-message
      "The name of this buffer is ‘%s’." (buffer-name))
          ⇒ "The name of this buffer is ‘strings.texi’."

     (format-message
      "The buffer object prints as `%s'." (current-buffer))
          ⇒ "The buffer object prints as ‘strings.texi’."

   By default, format specifications correspond to successive values
from OBJECTS. Thus, the first format specification in STRING uses the
first such value, the second format specification uses the second such
value, and so on. Any extra format specifications (those for which
there are no corresponding values) cause an error. Any extra values to
be formatted are ignored.

   A format specification can have a “field number”, which is a decimal
number immediately after the initial ‘%’, followed by a literal dollar
sign ‘$’. It causes the format specification to convert the argument
with the given number instead of the next argument. Field numbers start
at 1. A format can contain either numbered or unnumbered format
specifications but not both, except that ‘%%’ can be mixed with numbered
specifications.

     (format "%2$s, %3$s, %%, %1$s" "x" "y" "z")
          ⇒ "y, z, %, x"

   After the ‘%’ and any field number, you can put certain “flag
characters”.

   The flag ‘+’ inserts a plus sign before a nonnegative number, so that
it always has a sign. A space character as flag inserts a space before
a nonnegative number. (Otherwise, nonnegative numbers start with the
first digit.) These flags are useful for ensuring that nonnegative and
negative numbers use the same number of columns. They are ignored
except for ‘%d’, ‘%e’, ‘%f’, ‘%g’, and if both flags are used, ‘+’ takes
precedence.

   The flag ‘#’ specifies an alternate form which depends on the format
in use. For ‘%o’, it ensures that the result begins with a ‘0’. For
‘%x’ and ‘%X’, it prefixes nonzero results with ‘0x’ or ‘0X’. For ‘%e’
and ‘%f’, the ‘#’ flag means include a decimal point even if the
precision is zero. For ‘%g’, it always includes a decimal point, and
also forces any trailing zeros after the decimal point to be left in
place where they would otherwise be removed.

   The flag ‘0’ ensures that the padding consists of ‘0’ characters
instead of spaces. This flag is ignored for non-numerical specification
characters like ‘%s’, ‘%S’ and ‘%c’. These specification characters
accept the ‘0’ flag, but still pad with spaces.

   The flag ‘-’ causes any padding inserted by the width, if specified,
to be inserted on the right rather than the left. If both ‘-’ and ‘0’
are present, the ‘0’ flag is ignored.

     (format "%06d is padded on the left with zeros" 123)
          ⇒ "000123 is padded on the left with zeros"

     (format "'%-6d' is padded on the right" 123)
          ⇒ "'123 ' is padded on the right"

     (format "The word '%-7s' actually has %d letters in it."
             "foo" (length "foo"))
          ⇒ "The word 'foo ' actually has 3 letters in it."

   A specification can have a “width”, which is a decimal number that
appears after any field number and flags. If the printed representation
of the object contains fewer characters than this width, ‘format’
extends it with padding. Any padding introduced by the width normally
consists of spaces inserted on the left:

     (format "%5d is padded on the left with spaces" 123)
          ⇒ " 123 is padded on the left with spaces"

If the width is too small, ‘format’ does not truncate the object’s
printed representation. Thus, you can use a width to specify a minimum
spacing between columns with no risk of losing information. In the
following two examples, ‘%7s’ specifies a minimum width of 7. In the
first case, the string inserted in place of ‘%7s’ has only 3 letters,
and needs 4 blank spaces as padding. In the second case, the string
‘"specification"’ is 13 letters wide but is not truncated.

     (format "The word '%7s' has %d letters in it."
             "foo" (length "foo"))
          ⇒ "The word ' foo' has 3 letters in it."
     (format "The word '%7s' has %d letters in it."
             "specification" (length "specification"))
          ⇒ "The word 'specification' has 13 letters in it."

   All the specification characters allow an optional “precision” after
the field number, flags and width, if present. The precision is a
decimal-point ‘.’ followed by a digit-string. For the floating-point
specifications (‘%e’ and ‘%f’), the precision specifies how many digits
following the decimal point to show; if zero, the decimal-point itself
is also omitted. For ‘%g’, the precision specifies how many significant
digits to show (significant digits are the first digit before the
decimal point and all the digits after it). If the precision of %g is
zero or unspecified, it is treated as 1. For ‘%s’ and ‘%S’, the
precision truncates the string to the given width, so ‘%.3s’ shows only
the first three characters of the representation for OBJECT. For other
specification characters, the effect of precision is what the local
library functions of the ‘printf’ family produce.

   If you plan to use ‘read’ later on the formatted string to retrieve a
copy of the formatted value, use a specification that lets ‘read’
reconstruct the value. To format numbers in this reversible way you can
use ‘%s’ and ‘%S’, to format just integers you can also use ‘%d’, and to
format just nonnegative integers you can also use ‘#x%x’ and ‘#o%o’.
Other formats may be problematic; for example, ‘%d’ and ‘%g’ can
mishandle NaNs and can lose precision and type, and ‘#x%x’ and ‘#o%o’
can mishandle negative integers. *Note Input Functions::.

   The functions described in this section accept a fixed set of
specification characters. The next section describes a function
‘format-spec’ which can accept custom specification characters, such as
‘%a’ or ‘%z’.

8.7. Custom Format Strings

This introduced format-spec that performs a similar function to ‘format’, except it operates on format control strings that use arbitrary specification characters.

(setq my-site-info (list (cons ?s system-name) 
                                                 (cons ?t (symbol-name system-type)) 
                                                 (cons ?c system-configuration) 
                                                 (cons ?v emacs-version) 
                                                 (cons ?e invocation-name) 
                                                 (cons ?p (number-to-string (emacs-pid))) 
                                                 (cons ?a user-mail-address) 
                                                 (cons ?n user-full-name)))
(format-spec "%e %v (%c)" my-site-info) ;; "Emacs 27.2 (x86_64-apple-darwin19.6.0)"
(format-spec "%n <%a>" my-site-info) ;; "Yi Wang <[email protected]>"

   A format specification can include any number of the following flag
characters immediately after the ‘%’ to modify aspects of the
substitution.

‘0’
     This flag causes any padding specified by the width to consist of
     ‘0’ characters instead of spaces.

‘-’
     This flag causes any padding specified by the width to be inserted
     on the right rather than the left.

‘<’
     This flag causes the substitution to be truncated on the left to
     the given width, if specified.

‘>’
     This flag causes the substitution to be truncated on the right to
     the given width, if specified.

‘^’
     This flag converts the substituted text to upper case (*note Case
     Conversion::).

‘_’
     This flag converts the substituted text to lower case (*note Case
     Conversion::).

   The result of using contradictory flags (for instance, both upper and
lower case) is undefined.

   As is the case with ‘format’, a format specification can include a
width, which is a decimal number that appears after any flags. If a
substitution contains fewer characters than its specified width, it is
padded on the left:

     (format-spec "%8a is padded on the left with spaces"
                  '((?a . "alpha")))
          ⇒ " alpha is padded on the left with spaces"

Here is a more complicated example that combines several aforementioned features:

(setq my-battery-info (list (cons ?p "73")      ; Percentage
                                                        (cons ?L "Battery") ; Status
                                                        (cons ?t "2:23")    ; Remaining time
                                                        (cons ?c "24330")   ; Capacity
                                                        (cons ?r "10.6")))  ; Rate of discharge

(format-spec "%>^-3L : %3p%% (%05t left)" my-battery-info)

(format-spec "%>^-3L : %3p%% (%05t left)"
            (cons (cons ?L "AC")
                my-battery-info))

8.8. Case Conversion in Lisp

The character case functions change the case of single characters or of the contents of strings. The functions normally convert only alphabetic characters (the letters ‘A’ through ‘Z’ and ‘a’ through ‘z’, as well as non-ASCII letters); other characters are not altered.

(downcase ?X) ;; 120
(upcase ?x) ;; 88
(capitalize "test the function") ;; Test The Function
(capitalize "TEST THE FUNCTION") ;; Test The Function
(upcase-initials "test THE function") ;; Test THE Function

Note that case conversion is not a one-to-one mapping of codepoints
and length of the result may differ from length of the argument.
Furthermore, because passing a character forces return type to be a
character, functions are unable to perform proper substitution and
result may differ compared to treating a one-character string. For
example:

     (upcase "fi") ; note: single character, ligature "fi"
          ⇒ "FI"
     (upcase ?fi)
          ⇒ 64257 ; i.e. ?fi

   To avoid this, a character must first be converted into a string,
using ‘string’ function, before being passed to one of the casing
functions. Of course, no assumptions on the length of the result may be
made.

   Mapping for such special cases are taken from ‘special-uppercase’,
‘special-lowercase’ and ‘special-titlecase’ *Note Character
Properties::.

   *Note Text Comparison::, for functions that compare strings; some of
them ignore case differences, or can optionally ignore case differences.

8.9. The Case Table

This is not very related because I only use English and Chinese at the moment. I'll only check this when the need arises.

You can customize case conversion by installing a special “case table”.
A case table specifies the mapping between upper case and lower case
letters. It affects both the case conversion functions for Lisp objects
(see the previous section) and those that apply to text in the buffer
(*note Case Changes::). Each buffer has a case table; there is also a
standard case table which is used to initialize the case table of new
buffers.

   A case table is a char-table (*note Char-Tables::) whose subtype is
‘case-table’. This char-table maps each character into the
corresponding lower case character. It has three extra slots, which
hold related tables:

UPCASE
     The upcase table maps each character into the corresponding upper
     case character.
CANONICALIZE
     The canonicalize table maps all of a set of case-related characters
     into a particular member of that set.
EQUIVALENCES
     The equivalences table maps each one of a set of case-related
     characters into the next character in that set.

   In simple cases, all you need to specify is the mapping to
lower-case; the three related tables will be calculated automatically
from that one.

   For some languages, upper and lower case letters are not in
one-to-one correspondence. There may be two different lower case
letters with the same upper case equivalent. In these cases, you need
to specify the maps for both lower case and upper case.

   The extra table CANONICALIZE maps each character to a canonical
equivalent; any two characters that are related by case-conversion have
the same canonical equivalent character. For example, since ‘a’ and ‘A’
are related by case-conversion, they should have the same canonical
equivalent character (which should be either ‘a’ for both of them, or
‘A’ for both of them).

   The extra table EQUIVALENCES is a map that cyclically permutes each
equivalence class (of characters with the same canonical equivalent).
(For ordinary ASCII, this would map ‘a’ into ‘A’ and ‘A’ into ‘a’, and
likewise for each set of equivalent characters.)

   When constructing a case table, you can provide ‘nil’ for
CANONICALIZE; then Emacs fills in this slot from the lower case and
upper case mappings. You can also provide ‘nil’ for EQUIVALENCES; then
Emacs fills in this slot from CANONICALIZE. In a case table that is
actually in use, those components are non-‘nil’. Do not try to specify
EQUIVALENCES without also specifying CANONICALIZE.

   Here are the functions for working with case tables:

 – Function: case-table-p object
     This predicate returns non-‘nil’ if OBJECT is a valid case table.

 – Function: set-standard-case-table table
     This function makes TABLE the standard case table, so that it will
     be used in any buffers created subsequently.

 – Function: standard-case-table
     This returns the standard case table.

 – Function: current-case-table
     This function returns the current buffer’s case table.

 – Function: set-case-table table
     This sets the current buffer’s case table to TABLE.

 – Macro: with-case-table table body…
     The ‘with-case-table’ macro saves the current case table, makes
     TABLE the current case table, evaluates the BODY forms, and finally
     restores the case table. The return value is the value of the last
     form in BODY. The case table is restored even in case of an
     abnormal exit via ‘throw’ or error (*note Nonlocal Exits::).

   Some language environments modify the case conversions of ASCII
characters; for example, in the Turkish language environment, the ASCII
capital I is downcased into a Turkish dotless i (‘ı’). This can
interfere with code that requires ordinary ASCII case conversion, such
as implementations of ASCII-based network protocols. In that case, use
the ‘with-case-table’ macro with the variable ASCII-CASE-TABLE, which
stores the unmodified case table for the ASCII character set.

 – Variable: ascii-case-table
     The case table for the ASCII character set. This should not be
     modified by any language environment settings.

   The following three functions are convenient subroutines for packages
that define non-ASCII character sets. They modify the specified case
table CASE-TABLE; they also modify the standard syntax table. *Note
Syntax Tables::. Normally you would use these functions to change the
standard case table.

 – Function: set-case-syntax-pair uc lc case-table
     This function specifies a pair of corresponding letters, one upper
     case and one lower case.

 – Function: set-case-syntax-delims l r case-table
     This function makes characters L and R a matching pair of
     case-invariant delimiters.

 – Function: set-case-syntax char syntax case-table
     This function makes CHAR case-invariant, with syntax SYNTAX.

 – Command: describe-buffer-case-table
     This command displays a description of the contents of the current
     buffer’s case table.

9. Lists

9.1. Lists and Cons Cells

A list is a series of cons cells chained together, so that each cell
refers to the next one. There is one cons cell for each element of the
list. By convention, the CARs of the cons cells hold the elements of
the list, and the CDRs are used to chain the list (this asymmetry
between CAR and CDR is entirely a matter of convention; at the level of
cons cells, the CAR and CDR slots have similar properties). Hence, the
CDR slot of each cons cell in a list refers to the following cons cell.

Also by convention, the CDR of the last cons cell in a list is ‘nil’. We call such a ‘nil’-terminated structure a “proper list”. In Emacs Lisp, the symbol ‘nil’ is both a symbol and a list with no elements. For convenience, the symbol ‘nil’ is considered to have ‘nil’ as its CDR (and also as its CAR). The CDR of a proper list is always a proper list. The CDR of a nonempty proper list is a proper list containing all the elements except the first.


9.2. Predicates on Lists

;; This function returns ‘t’ if OBJECT is a cons cell, ‘nil’ otherwise. 
(consp '('test . 'random)) ;; t
;; nil’ is not a cons cell, although it _is_ a list.
(consp nil) ;; nil
;; This function returns ‘t’ if OBJECT is an atom, ‘nil’ otherwise.
(atom "t") ;; t
(atom 1) ;; t
;; All objects except cons cells are atoms.  The symbol ‘nil’ is an
;; atom and is also a list; it is the only Lisp object that is both.
(atom nil) ;; t
(listp nil) ;; t
;; (atom OBJECT) ≡ (not (consp OBJECT))


;; This function returns ‘t’ if OBJECT is a cons cell or ‘nil’.
;; Otherwise, it returns ‘nil’.
(listp nil) ;; t
(listp '(1)) ;; t
(listp '()) ;; t


;; This function is the opposite of ‘listp’: it returns ‘t’ if OBJECT
;; is not a list.  Otherwise, it returns ‘nil’.
(nlistp '(1)) ;; nil
(nlistp nil) ;; nil
;; (listp OBJECT) ≡ (not (nlistp OBJECT))


;; This function returns ‘t’ if OBJECT is ‘nil’, and returns ‘nil’ otherwise
;; This function is identical to ‘not’, but as a matter of
;; clarity we use ‘null’ when OBJECT is considered a list and ‘not
;; when it is considered a truth value
(null nil) ;; t


;; This function returns the length of OBJECT if it is a proper list,
;; 'nil' otherwise
(proper-list-p '(a b c)) ;; 3
(proper-list-p '(a b . c)) ;; nil

9.3. Accessing Elements of Lists

Basic operations.

(car '((a . b)  c)) ;; (a . b)
(car nil)           ;; nil
(car '())           ;; nil

(cdr '((a . b)  c)) ;; (c)
(cdr nil)           ;; nil
(cdr '())           ;; nil

(car-safe 1) ;; nil
(car-safe '(a b)) ;; a
(listp (car-safe '(a b))) ;; nil

;; (car-safe OBJECT)
;; 
;; (let ((x OBJECT))
;;   (if (consp x) 
;;       (car x) nil))

(cdr-safe 1) ;; nil
(cdr-safe '(a b)) ;; (b)
(listp (cdr-safe '(a b))) ;; t
;; (cdr-safe OBJECT)
;; 
;; (let ((x OBJECT))
;;   (if (consp x) 
;;       (cdr x) nil))

Note the following about car and cdr. This is because for the object '(a b), its CAR is an atom a, while its CDR is always list whose CAR is b.

(listp (car '(a b))) ;; nil

(listp (cdr '(a b))) ;; t

(listp (car (cdr '(a b)))) ;; nil

(listp (cdr '(a . b))) ;; nil

Continuation of basic operations.

(setq x (list 1 "test" ?a))
;; This is a macro
;; This macro provides a convenient way to examine the CAR of a list,
;; and take it off the list, all at once.  It operates on the list
;; stored in LISTNAME.  It removes the first element from the list,
;; saves the CDR into LISTNAME, then returns the removed element.
;; 
;; In the simplest case, LISTNAME is an unquoted symbol naming a list;
;; in that case, this macro is equivalent to
;; ‘(prog1 (car listname) (setq listname (cdr listname)))’.

(pop x) ;; 1
(progn x) ;; ("test" 97)

(setq x (list 1 "test" ?a))

;; This function returns the Nth element of LIST.  Elements are
;; numbered starting with zero, so the CAR of LIST is element number
;; zero.  If the length of LIST is N or less, the value is ‘nil’.
(nth 0 x) ;; 1
(nth 1000 x) ;; nil
;; (nth n x) ≡ (car (nthcdr n x))


;; This function returns the Nth CDR of LIST.  In other words, it
;; skips past the first N links of LIST and returns what follows.

;; If N is zero, ‘nthcdr’ returns all of LIST.  If the length of LIST
;; is N or less, ‘nthcdr’ returns ‘nil’.
(nthcdr 1 x) ;; ("test" 97)
(nthcdr 0 x) ;; (1 "test" 97)
(nthcdr 10000 x) ;; nil


;; This function returns the last link of LIST.  The ‘car’ of this
;; link is the list’s last element.  If LIST is null, ‘nil’ is
;; returned.  If N is non-‘nil’, the Nth-to-last link is returned
;; instead, or the whole of LIST if N is bigger than LIST’s length.
(last x) ;; (97)
(last x 0) ;; nil
(last x 1) ;; (97)
(last x 10) ;; (1 "test" 97)

;; This function returns the length of LIST, with no risk of either an
;; error or an infinite loop.  It generally returns the number of
;; distinct cons cells in the list.  However, for circular lists, the
;; value is just an upper bound; it is often too large.

;; If LIST is not ‘nil’ or a cons cell, ‘safe-length’ returns 0.
(safe-length x) ;; 3
;; only one cons cell
(safe-length '(a . b)) ;; 1
(safe-length 1) ;; 0

(setq deep-x `(,x (,x ,x)))
;; This is the same as ‘(car (car CONS-CELL))’.
(caar deep-x) ;; 1
;; This is the same as ‘(car (cdr CONS-CELL))’ or ‘(nth 1 CONS-CELL)’.
(cadr deep-x) ;; ((1 "test" 97) (1 "test" 97))

;; In addition to the above, 24 additional compositions of ‘car’ and
;; cdr’ are defined as ‘cXXXr’ and ‘cXXXXr’, where each ‘X’ is either ‘a’
;; or ‘d’.  ‘cadr’, ‘caddr’, and ‘cadddr’ pick out the second, third or
;; fourth elements of a list, respectively.  ‘cl-lib’ provides the same

;; This function returns the list X with the last element, or the last
;; N elements, removed.
(butlast x) ;; (1 "test")
(butlast x 2) ;; (1)
(butlast x 10) ;; nil

;; This is a version of ‘butlast’ that works by destructively
;; modifying the ‘cdr’ of the appropriate element, rather than making
;; a copy of the list.
(nbutlast x) ;; (1 "test")

9.4. Building Cons Cells and Lists

(cons 1 '(2)) ;; (1  2), CAR holds 1 and CDR holds a list (2)
(cons 1 '()) ;; (1), CAR holds 1 and CDR holds nil
(cons 1 2) ;; (1 . 2), CAR holds 1 and CDR holds 2

;; cons’ is often used to add a single element to the front of a
;; list.  This is called “consing the element onto the list”.  (1) For
;; example:

(setq list '(1))
(setq newelt 2)
(setq list (cons newelt list)) ;; (2 1)

;; This function creates a list with OBJECTS as its elements.  The
;; resulting list is always ‘nil’-terminated.  If no OBJECTS are
;; given, the empty list is returned.
(list 1 2 3 4)

;; This function creates a list of LENGTH elements, in which each
;; element is OBJECT.  Compare ‘make-list’ with ‘make-string’ (*note
;; Creating Strings::).
(make-list 3 'sym) ;; (sym sym sym)

9.4.1. Function: append &rest sequences

This function returns a list containing all the elements of SEQUENCES. The SEQUENCES may be lists, vectors, bool-vectors, or strings, but the last one should usually be a list. All arguments except the last one are copied, so none of the arguments is altered. (See ‘nconc’ in *note Rearrangement::, for a way to join lists with no copying.)

More generally, the final argument to ‘append’ may be any Lisp object. The final argument is not copied or converted; it becomes the CDR of the last cons cell in the new list. If the final argument is itself a list, then its elements become in effect elements of the result list. If the final element is not a list, the result is a dotted list since its final CDR is not ‘nil’ as required in a proper list (*note Cons Cells::).

(setq trees '(pine oak)) ;; (pine oak)

(setq more-trees (append '(maple birch) trees)) ;; (maple birch pine oak)
(eq trees (cddr more-trees)) ;; t

You can see how ‘append’ works by looking at a box diagram. The variable ‘trees’ is set to the list ‘(pine oak)’ and then the variable ‘more-trees’ is set to the list ‘(maple birch pine oak)’. However, the variable ‘trees’ continues to refer to the original list:

     more-trees                trees
     |                           |
     |     --- ---      --- ---   -> --- ---      --- ---
      --> |   |   |--> |   |   |--> |   |   |--> |   |   |--> nil
           --- ---      --- ---      --- ---      --- ---
            |            |            |            |
            |            |            |            |
             --> maple    -->birch     --> pine     --> oak

An empty sequence contributes nothing to the value returned by ‘append’. As a consequence of this, a final ‘nil’ argument forces a copy of the previous argument:

(setq trees '(pine oak)) ;; (pine oak)
(setq wood (append trees nil)) ;; (pine oak)
(eq wood trees) ;; nil
(eq (cdr wood) (cdr trees)) ;; nil

Work with Vectors.

(append [a b] "cd" nil) ;; (a b 99 100), append returns a list
(string-to-char "c") ;; 99
(string-to-char "d") ;; 100

Combined with apply.

(apply 'append '((a b c) nil (x y z) nil)) ;; (a b c x y z)

No arguments.

(append) ;; nil

Final argument is not a list.

(append '(x y) 'z) ;; (x y . z)
;; This example shows that when the final argument is a sequence but
;; not a list, the sequence’s elements do not become elements of the
;; resulting list.  Instead, the sequence becomes the final CDR, like any
;; other non-list final argument.
(append '(x y) [z]) ;; (x y . [z])

9.4.2. Function: copy-tree tree &optional vecp

This function returns a copy of the tree TREE. If TREE is a cons cell, this makes a new cons cell with the same CAR and CDR, then recursively copies the CAR and CDR in the same way.

Normally, when TREE is anything other than a cons cell, ‘copy-tree’ simply returns TREE. However, if VECP is non-‘nil’, it copies vectors too (and operates recursively on their elements).

(copy-tree '(x y)) ;; (x y)
(copy-tree '(x . y)) ;; (x . y)
(copy-tree '(x '(xx yy) y)) ;; (x '(xx yy) y)
;; TREE is not a cons cell
(setq tree "test")
(setq new-tree (copy-tree tree))
(eq tree "test") ;; nil
(eq tree new-tree) ;; t

;; turn on vecp
(setq tree [1 2 3])
;; simply return TREE
(setq new-tree (copy-tree tree)) ;; [1 2 3]
(eq tree new-tree) ;; t

;; copy TREE and return
(setq new-tree (copy-tree new-tree t)) ;; [1 2 3]
(eq tree new-tree) ;; nil

9.4.3. Function: flatten-tree tree

This function returns a “flattened” copy of TREE, that is, a list containing all the non-‘nil’ terminal nodes, or leaves, of the tree of cons cells rooted at TREE. Leaves in the returned list are in the same order as in TREE.

(flatten-tree '(1 (2 . 3) nil (4 5 (6)) 7)) ;; (1 2 3 4 5 6 7)

9.4.4. Function: number-sequence from &optional to separation

This function returns a list of numbers starting with FROM and incrementing by SEPARATION, and ending at or just before TO. SEPARATION can be positive or negative and defaults to 1. If TO is ‘nil’ or numerically equal to FROM, the value is the one-element list ‘(FROM)’. If TO is less than FROM with a positive SEPARATION, or greater than FROM with a negative SEPARATION, the value is ‘nil’ because those arguments specify an empty sequence.

If SEPARATION is 0 and TO is neither ‘nil’ nor numerically equal to FROM, ‘number-sequence’ signals an error, since those arguments specify an infinite sequence.

All arguments are numbers. Floating-point arguments can be tricky, because floating-point arithmetic is inexact. For instance, depending on the machine, it may quite well happen that ‘(number-sequence 0.4 0.6 0.2)’ returns the one element list ‘(0.4)’, whereas ‘(number-sequence 0.4 0.8 0.2)’ returns a list with three elements. The Nth element of the list is computed by the exact formula ‘(+ FROM (* N SEPARATION))’. Thus, if one wants to make sure that TO is included in the list, one can pass an expression of this exact type for TO. Alternatively, one can replace TO with a slightly larger value (or a slightly more negative value if SEPARATION is negative).

(number-sequence 4 9) ;; (4 5 6 7 8 9)

9.5. Modifying List Variables

9.5.1. Macro: push element listname

This macro creates a new list whose CAR is ELEMENT and whose CDR is the list specified by LISTNAME, and saves that list in LISTNAME. In the simplest case, LISTNAME is an unquoted symbol naming a list, and this macro is equivalent to ‘(setq LISTNAME (cons ELEMENT LISTNAME))’.

(setq l '(a b)) ;; (a b)
;; inserts to the beginning of the list
(push 'c l) ;; (c a b)
l ;; (c a b)

9.5.2. add-to-list symbol element &optional append compare-fn

This documentation seems to be written by a completely different guy as the tone is priceless.

This function sets the variable SYMBOL by consing ELEMENT onto the old value, if ELEMENT is not already a member of that value. It returns the resulting list, whether updated or not. The value of SYMBOL had better be a list already before the call. ‘add-to-list’ uses COMPARE-FN to compare ELEMENT against existing list members; if COMPARE-FN is ‘nil’, it uses ‘equal’.

Normally, if ELEMENT is added, it is added to the front of SYMBOL, but if the optional argument APPEND is non-‘nil’, it is added at the end.

The argument SYMBOL is not implicitly quoted; ‘add-to-list’ is an ordinary function, like ‘set’ and unlike ‘setq’. Quote the argument yourself if that is what you want.

Do not use this function when SYMBOL refers to a lexical variable.

(setq foo '(a b)) ;; (a b)
(add-to-list 'foo 'c) ;; (c a b)
(add-to-list 'foo 'b) ;; (c a b)
foo ;; (c a b)

9.5.3. add-to-ordered-list symbol element &optional order

This function sets the variable SYMBOL by inserting ELEMENT into the old value, which must be a list, at the position specified by ORDER. If ELEMENT is already a member of the list, its position in the list is adjusted according to ORDER. Membership is tested using ‘eq’. This function returns the resulting list, whether updated or not.

The ORDER is typically a number (integer or float), and the elements of the list are sorted in non-decreasing numerical order.

ORDER may also be omitted or ‘nil’. Then the numeric order of ELEMENT stays unchanged if it already has one; otherwise, ELEMENT has no numeric order. Elements without a numeric list order are placed at the end of the list, in no particular order.

Any other value for ORDER removes the numeric order of ELEMENT if it already has one; otherwise, it is equivalent to ‘nil’.

The argument SYMBOL is not implicitly quoted; ‘add-to-ordered-list’ is an ordinary function, like ‘set’ and unlike ‘setq’. Quote the argument yourself if necessary.

The ordering information is stored in a hash table on SYMBOL’s ‘list-order’ property. SYMBOL cannot refer to a lexical variable.

(setq foo '())
(add-to-ordered-list 'foo 'a 1) ;; (a)
(add-to-ordered-list 'foo 'c 1) ;; (c a)
(add-to-ordered-list 'foo 'b 2) ;; (c a b)
(add-to-ordered-list 'foo 'b 1) ;; (b c a)
foo ;; (b c a)

9.6. Altering List Elements with ‘setcar’

Changing the CAR of a cons cell is done with ‘setcar’. When used on a list, ‘setcar’ replaces one element of a list with a different element.

9.6.1. Function: setcar cons object

This function stores OBJECT as the new CAR of CONS, replacing its previous CAR. In other words, it changes the CAR slot of CONS to refer to OBJECT. It returns the value OBJECT. For example:

(setq x (list 1 2)) ;; (1 2)
(setcar x 4) ;; 4
x ;; (4 2)

When a cons cell is part of the shared structure of several lists, storing a new CAR into the cons changes one element of each of these lists. Here is an example:

;; Create two lists that are partly shared.
(setq x1 (list 'a 'b 'c)) ;; (a b c)
(setq x2 (cons 'z (cdr x1))) ;; (z b c)
(setcar (cdr x1) 'foo) ;; foo
x1 ;; (a foo c)
x2 ;; (z foo c)

;; Replace the CAR of a link that is not shared.
(setcar x1 'baz) ;; baz
x1 ;; (baz foo c)
x2 ;; (z foo c)

Graphical depiction of the code above.

     x1:
      --------------       --------------       --------------
     | car   | cdr  |     | car   | cdr  |     | car   | cdr  |
     |   a   |   o------->|   b   |   o------->|   c   |  nil |
     |       |      |  -->|       |      |     |       |      |
      --------------  |    --------------       --------------
                      |
     x2:              |
      --------------  |
     | car   | cdr  | |
     |   z   |   o----
     |       |      |
      --------------

9.7. Altering the CDR of a List

The lowest-level primitive for modifying a CDR is ‘setcdr’:

9.7.1. Function: setcdr cons object

This function stores OBJECT as the new CDR of CONS, replacing its previous CDR. In other words, it changes the CDR slot of CONS to refer to OBJECT. It returns the value OBJECT.

(setq x (list 1 2 3)) ;; (1 2 3)
(setcdr x '(4)) ;; (4)
x ;; (1 4)

(setcdr x 4) ;; 4
x ;; (1 . 4)

You can delete elements from the middle of a list by altering the CDRs of the cons cells in the list. For example, here we delete the second element, ‘b’, from the list ‘(a b c)’, by changing the CDR of the first cons cell:

(setq x1 (list 'a 'b 'c)) ;; (a b c)
(setcdr x1 (cdr (cdr x1))) ;; (c)
x1 ;; (a c)

Graphical representation of the above:

                        --------------------
                       |                    |
      --------------   |   --------------   |    --------------
     | car   | cdr  |  |  | car   | cdr  |   -->| car   | cdr  |
     |   a   |   o-----   |   b   |   o-------->|   c   |  nil |
     |       |      |     |       |      |      |       |      |
      --------------       --------------        --------------

You can also use this to insert a new element.

(setq x1 (list 'a 'b 'c)) ;; (a b c)
(setcdr x1 `(d ,@(cdr x1))) ;; (d b c)
;; equivalent to the following
;; (setcdr x1 (cons 'd (cdr x1)))
x1 ;; (a d b c)

Graphical representation of the above.

      --------------        -------------       -------------
     | car  | cdr   |      | car  | cdr  |     | car  | cdr  |
     |   a  |   o   |   -->|   b  |   o------->|   c  |  nil |
     |      |   |   |  |   |      |      |     |      |      |
      --------- | --   |    -------------       -------------
                |      |
          -----         --------
         |                      |
         |    ---------------   |
         |   | car   | cdr   |  |
          -->|   d   |   o------
             |       |       |
              ---------------

9.8. Functions that Rearrange Lists

Here are some functions that rearrange lists destructively by modifying the CDRs of their component cons cells. These functions are destructive because they chew up the original lists passed to them as arguments, relinking their cons cells to form a new list that is the returned value.

9.8.1. Function: nconc &rest lists

This function returns a list containing all the elements of LISTS. Unlike ‘append’ (*note 9.4.1), the LISTS are not copied. Instead, the last CDR of each of the LISTS is changed to refer to the following list. The last of the LISTS is not altered.

(setq x (list 1 2 3)) ;; (1 2 3)
(nconc x '(4 5)) ;; (1 2 3 4 5)
x ;; (1 2 3 4 5)

Since the last argument of ‘nconc’ is not itself modified, it is reasonable to use a constant list, such as ‘'(4 5)’, as in the above example. For the same reason, the last argument need not be a list:

(setq x (list 1 2 3)) ;; (1 2 3)
(nconc x 'z) ;; (1 2 3 . z)
x ;; (1 2 3 . z)

However, the other arguments (all but the last) should be mutable lists.

A common pitfall is to use a constant list as a non-last argument to ‘nconc’. If you do this, the resulting behavior is undefined. It is possible that your program will change each time you run it! Here is what might happen (though this is not guaranteed to happen):

(defun add-foo (x)            ; We want this function to add
    (nconc '(foo) x))           ;   foo’ to the front of its arg.
(symbol-function 'add-foo) ;; (lambda (x) (nconc '(foo) x))
(setq xx (add-foo '(1 2))) ;; (foo 1 2)
;; intention is that there will be more 'foo' at the beginning of the list
;; but that is not the case
(setq xx (add-foo '(3 4))) ;; (foo 1 2 3 4)
(setq xx (add-foo '(3 4))) ;; (foo 1 2 3 4 3 4)

9.9. Using Lists as Sets

If you ignore the order of an element in a list, then it becomes a set, though this list could have duplicate elements.

9.9.1. Function: memq object list

Check if OBJECT is a member of LIST by comparing the OBJECT and element of LIST are the same Lisp object. If it is, ‘memq’ returns a list starting with the first occurrence of OBJECT. Otherwise, it returns ‘nil’. The letter ‘q’ in ‘memq’ says that it uses ‘eq’ to compare OBJECT against the elements of the list.

(memq 'b '(a b c b a)) ;; (b c b a)
(setq test '(1 2))
(memq '(1 2) '(1 test)) ;; nil

9.9.2. Function: delq object list

This function destructively removes all elements ‘eq’ to OBJECT from LIST, and returns the resulting list. The letter ‘q’ in ‘delq’ says that it uses ‘eq’ to compare OBJECT against the elements of the list, like ‘memq’ and ‘remq’.

Typically, when you invoke ‘delq’, you should use the return value by assigning it to the variable which held the original list. The reason for this is explained below.

The ‘delq’ function deletes elements from the front of the list by simply advancing down the list, and returning a sublist that starts after those elements. For example:

(delq 'a '(a b c)) ≡ (cdr '(a b c))

(delq 'a '(a b c)) ;; (b c)
(cdr '(a b c)) ;; (b c)

When an element to be deleted appears in the middle of the list, removing it involves changing the CDRs (*note 9.7.1).

(setq sample-list (list 'a 'b 'c '(4))) ;; (a b c (4))
(delq 'a sample-list) ;; (b c (4))
sample-list ;; (a b c (4))
(delq 'c sample-list) ;; (a b (4))
sample-list ;; (a b (4))

Note that ‘(delq 'c sample-list)’ modifies ‘sample-list’ to splice out the third element, but ‘(delq 'a sample-list)’ does not splice anything—it just returns a shorter list. Don’t assume that a variable which formerly held the argument LIST now has fewer elements, or that it still holds the original list! Instead, save the result of ‘delq’ and use that. Most often we store the result back into the variable that held the original list:

(setq flowers '(rose sunflower)) ;; (rose sunflower)
(setq flowers (delq 'rose flowers)) ;; (sunflower)
flowers ;; (sunflower)

In the following example, the ‘(list 4)’ that ‘delq’ attempts to match and the ‘(4)’ in the ‘sample-list’ are ‘equal’ but not ‘eq’:

(delq (list 4) sample-list) ;; (a b (4))
sample-list ;; (a b (4))

9.10. Association Lists

Basically a dictionary in python.

Mapping from keys to values.

It is a list of cons cells called “associations”: the CAR of each cons cell is the “key”, and the CDR is the “associated value”.

Here is an example of an alist. The key ‘pine’ is associated with the value ‘cones’; the key ‘oak’ is associated with ‘acorns’; and the key ‘maple’ is associated with ‘seeds’.

((pine . cones)
 (oak . acorns)
 (maple . seeds))

Both the values and the keys in an alist may be any Lisp objects.* For example, in the following alist, the symbol ‘a’ is associated with the number ‘1’, and the string ‘"b"’ is associated with the list ‘(2 3)’, which is the CDR of the alist element:

((a . 1) ("b" 2 3))

Sometimes it is better to design an alist to store the associated value in the CAR of the CDR of the element. Here is an example of such an alist:

;; red is in the CAR of the CDR of (rose red)
((rose red) (lily white) (buttercup yellow))

Here we regard ‘red’ as the value associated with ‘rose’. One advantage of this kind of alist is that you can store other related information—even a list of other items—in the CDR of the CDR. One disadvantage is that you cannot use ‘rassq’ (see below) to find the element containing a given value. When neither of these considerations is important, the choice is a matter of taste, as long as you are consistent about it for any given alist.

The same alist shown above could be regarded as having the associated value in the CDR of the element; the value associated with ‘rose’ would be the list ‘(red)’.

Association lists are often used to record information that you might otherwise keep on a stack, since new associations may be added easily to the front of the list. When searching an association list for an association with a given key, the first one found is returned, if there is more than one.

In Emacs Lisp, it is not an error if an element of an association list is not a cons cell. The alist search functions simply ignore such elements. Many other versions of Lisp signal errors in such cases.

Note that 9.11 are similar to association lists in several respects. A property list behaves like an association list in which each key can occur only once.

9.10.1. Function: assoc key alist &optional testfn

This function returns the first association for KEY in ALIST, comparing KEY against the alist elements using TESTFN if it is non-‘nil’ and ‘equal’ otherwise (see 5). It returns ‘nil’ if no association in ALIST has a CAR equal to KEY. For example:

(setq trees '((pine . cones) (oak . acorns) (maple . seeds)))

(assoc 'oak trees)

(cdr (assoc 'oak trees))

(assoc 'birch trees)

Here is another example, in which the keys and values are not symbols:

(setq needles-per-cluster
    '((2 "Austrian Pine" "Red Pine")
        (3 "Pitch Pine")
        (5 "White Pine")))

(cdr (assoc 3 needles-per-cluster))
(cdr (assoc 2 needles-per-cluster))

The function ‘assoc-string’ is much like ‘assoc’ except that it ignores certain differences between strings. *Note Text Comparison::.


9.10.2. Function: rassoc value alist

Search value of the mapping. r in the function name means "reverse".

This function returns the first association with value VALUE in ALIST. It returns ‘nil’ if no association in ALIST has a CDR ‘equal’ to VALUE.

(setq needles-per-cluster
    '((2 "Austrian Pine" "Red Pine")
        (3 "Pitch Pine")
        (5 "White Pine")))

(rassoc "Austrian Pine" needles-per-cluster) ;; nil
(rassoc "White Pine" needles-per-cluster) ;; nil
(rassoc '("White Pine") needles-per-cluster) ;; (5 "White Pine")

9.10.3. Function: assq key alist

This function is like ‘assoc’ in that it returns the first association for KEY in ALIST, but it makes the comparison using ‘eq’. ‘assq’ returns ‘nil’ if no association in ALIST has a CAR ‘eq’ to KEY. This function is used more often than ‘assoc’, since ‘eq’ is faster than ‘equal’ and most alists use symbols as keys.

(setq trees '((pine . cones) (oak . acorns) (maple . seeds)))
(assq 'pine trees)

On the other hand, ‘assq’ is not usually useful in alists where the keys may not be symbols:

(setq leaves
    '(("simple leaves" . oak)
        ("compound leaves" . horsechestnut)))
;; this is affected by eq's behaviour
(assq "simple leaves" leaves) ;; nil or ("simple leaves" . oak)
(assoc "simple leaves" leaves) ;; ("simple leaves" . oak)

9.10.4. Function: alist-get key alist &optional default remove testfn

This function is similar to ‘assq’. It finds the first association ‘(KEY . VALUE)’ by comparing KEY with ALIST elements, and, if found, returns the VALUE of that association. If no association is found, the function returns DEFAULT. Comparison of KEY against ALIST elements uses the function specified by TESTFN, defaulting to ‘eq’.

This is a generalized variable (*note Generalized Variables::) that can be used to change a value with ‘setf’. When using it to set a value, optional argument REMOVE non-‘nil’ means to remove KEY’s association from ALIST if the new value is ‘eql’ to DEFAULT.

9.10.5. Function: rassq value alist

This function returns the first association with value VALUE in ALIST. It returns ‘nil’ if no association in ALIST has a CDR ‘eq’ to VALUE.

‘rassq’ is like ‘assq’ except that it compares the CDR of each ALIST association instead of the CAR. You can think of this as reverse ‘assq’, finding the key for a given value.

(setq trees '((pine . cones) (oak . acorns) (maple . seeds)))

(rassq 'acorns trees)
(rassq 'spores trees)

‘rassq’ cannot search for a value stored in the CAR of the CDR of an element:

(setq colors '((rose red) (lily white) (buttercup yellow)))

;; In this case, the CDR of the association ‘(lily white)’ is not the
;; symbol ‘white’, but rather the list ‘(white)’.  This becomes
;; clearer if the association is written in dotted pair notation:
(rassq 'white colors) ;; (lily . whitelist)
(setq white "white color")
(setq whitelist '(white))
(setq colors '((rose red) (lily . whitelist) (buttercup yellow)))
;; this works because the eq function receives the same whitelist object.
(rassq 'whitelist colors) ;; (lily . whitelist)

9.10.6. Function: assoc-default key alist &optional test default

This function searches ALIST for a match for KEY. For each element of ALIST, it compares the element (if it is an atom) or the element’s CAR (if it is a cons) against KEY, by calling TEST with two arguments: the element or its CAR, and KEY. The arguments are passed in that order so that you can get useful results using ‘string-match’ with an alist that contains regular expressions (*note Regexp Search::). If TEST is omitted or ‘nil’, ‘equal’ is used for comparison.

If an alist element matches KEY by this criterion, then ‘assoc-default’ returns a value based on this element. If the element is a cons, then the value is the element’s CDR. Otherwise, the return value is DEFAULT.

If no alist element matches KEY, ‘assoc-default’ returns ‘nil’.

9.10.7. Function: copy-alist alist

This function returns a two-level deep copy of ALIST: it creates a new copy of each association, so that you can alter the associations of the new alist without changing the old one.

(setq needles-per-cluster
      '((2 . ("Austrian Pine" "Red Pine"))
        (3 . ("Pitch Pine"))
        (5 . ("White Pine"))))
(setq copy (copy-alist needles-per-cluster))

;; association lists are different
(eq needles-per-cluster copy) ;; nil
(equal needles-per-cluster copy) ;; t

;; assocations are different
(eq (car needles-per-cluster) (car copy)) ;; nil
(equal (car needles-per-cluster) (car copy)) ;; t

;; contents in the cons cells are the same
(eq (car (car needles-per-cluster)) (car (car copy))) ;; t

This example shows how ‘copy-alist’ makes it possible to change the associations of one copy without affecting the other:

(setcdr (assq 3 copy) '("Martian Vacuum Pine"))
(cdr (assq 3 needles-per-cluster))

9.10.8. Function: assq-delete-all key alist

This function deletes from ALIST all the elements whose CAR is ‘eq’ to KEY, much as if you used ‘delq’ to delete each such element one by one. It returns the shortened alist, and often modifies the original list structure of ALIST. For correct results, use the return value of ‘assq-delete-all’ rather than looking at the saved value of ALIST.

(setq alist (list '(foo 1) '(bar 2) '(foo 3) '(lose 4)))

(assq-delete-all 'foo alist) ;; ((bar 2) (lose 4))
alist ;; ((foo 1) (bar 2) (lose 4))

9.10.9. Function: assoc-delete-all key alist &optional test

This function is like ‘assq-delete-all’ except that it accepts an optional argument TEST, a predicate function to compare the keys in ALIST. If omitted or ‘nil’, TEST defaults to ‘equal’. As ‘assq-delete-all’, this function often modifies the original list structure of ALIST.

9.10.10. Function: rassq-delete-all value alist

This function deletes from ALIST all the elements whose CDR is ‘eq’ to VALUE. It returns the shortened alist, and often modifies the original list structure of ALIST. ‘rassq-delete-all’ is like ‘assq-delete-all’ except that it compares the CDR of each ALIST association instead of the CAR.

9.10.11. Macro: let-alist alist body

Looks like accessing the value with keys that are prefixed with a dot.

seems to have a typo.

Creates a binding for each symbol used as keys the association list

Creates a binding for each symbol used as keys in the association list ALIST, prefixed with dot. This can be useful when accessing several items in the same association list, and it’s best understood through a simple example:

(setq colors '((rose . red) (lily . white) (buttercup . yellow)))

(let-alist colors
  (if (eq .rose 'red)
      .lily)) ;; white

The BODY is inspected at compilation time, and only the symbols that appear in BODY with a ‘.’ as the first character in the symbol name will be bound. Finding the keys is done with ‘assq’, and the ‘cdr’ of the return value of this ‘assq’ is assigned as the value for the binding.

Nested association lists is supported:

(setq colors '((rose . red) (lily (belladonna . yellow) (brindisi . pink))))

(let-alist colors
  (if (eq .rose 'red)
      .lily.belladonna)) ;; yellow

Nesting ‘let-alist’ inside each other is allowed, but the code in the inner ‘let-alist’ can’t access the variables bound by the outer ‘let-alist’.

9.11. Property Lists

10. log time

Table 1: Clock summary at [2022-04-10 Sun 22:23]
Headline Time
Total time 7:11
Intro 0:06
log time 7:05