{"id":16313411,"url":"https://github.com/alhassy/elispcheatsheet","last_synced_at":"2025-03-16T14:30:47.942Z","repository":{"id":53761324,"uuid":"171197567","full_name":"alhassy/ElispCheatSheet","owner":"alhassy","description":"Quick reference to the core language of Emacs ---Editor MACroS.","archived":false,"fork":false,"pushed_at":"2020-04-27T03:08:53.000Z","size":1724,"stargazers_count":232,"open_issues_count":2,"forks_count":18,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-02-27T10:35:20.081Z","etag":null,"topics":["cheatsheet","common-lisp","emacs","emacs-lisp","html","lisp","pdf","reference"],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alhassy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-02-18T01:58:45.000Z","updated_at":"2025-02-24T01:27:41.000Z","dependencies_parsed_at":"2022-09-13T20:31:30.987Z","dependency_job_id":null,"html_url":"https://github.com/alhassy/ElispCheatSheet","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alhassy%2FElispCheatSheet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alhassy%2FElispCheatSheet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alhassy%2FElispCheatSheet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alhassy%2FElispCheatSheet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alhassy","download_url":"https://codeload.github.com/alhassy/ElispCheatSheet/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243818195,"owners_count":20352629,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cheatsheet","common-lisp","emacs","emacs-lisp","html","lisp","pdf","reference"],"created_at":"2024-10-10T21:51:09.063Z","updated_at":"2025-03-16T14:30:47.590Z","avatar_url":"https://github.com/alhassy.png","language":null,"readme":"\u003ch1\u003e ElispCheatSheet \u003c/h1\u003e\n\nQuick reference to the core language of Emacs \u0026#x2014;Editor MACroS.\n\n◈ [Website](https://alhassy.github.io/ElispCheatSheet/) ◈\n\n( It's mostly Common Lisp in Elisp syntax, for now; based on reading Land of Lisp. )\n\n**The listing sheet, as PDF, can be found\n[here](\u003chttps://github.com/alhassy/ElispCheatSheet/blob/master/CheatSheet.pdf\u003e)**,\nwhile below is an unruly html rendition.\n\nThis reference sheet is built around\n[an Org-mode CheatSheet system](https://github.com/alhassy/CheatSheet).\n\n\n# Table of Contents\n\n1.  [Functions](#orgcae400a)\n2.  [Quotes, Quasi-Quotes, and Unquotes](#orge624d54)\n3.  [Reads](#orgdb68da1)\n4.  [Variables](#org943c427)\n5.  [Lists and List-Like Structures](#orgbc87d9e)\n6.  [Generic Setters](#org8ccfbc7)\n7.  [Records](#org71dcb45)\n8.  [Block of Code](#org9c71fdf)\n9.  [Conditionals](#orgaa669ec)\n10. [Loops](#org45458fb)\n11. [Exception Handling](#orgeb7a6f7)\n12. [Types \u0026 Overloading](#org825332f)\n13. [Macros](#orgc487ae3)\n14. [`read` and `print`](#org7ece87e)\n\n\n\n\n\n\n\n\n\n\n\n\n\n*Everything is a list!*\n\n-   To find out more about `name` execute `(describe-symbol 'name)`!\n    -   After the closing parens invoke `C-x C-e` to evaluate.\n-   To find out more about a key press, execute `C-h k` then the key press.\n-   To find out more about the current mode you're in, execute `C-h m` or\n    `describe-mode`. Essentially a comprehensive yet terse reference is provided.\n\n\n\u003ca id=\"orgcae400a\"\u003e\u003c/a\u003e\n\n# Functions\n\n-   Function invocation: `(f x₀ x₁ … xₙ)`. E.g., `(+ 3 4)` or `(message \"hello\")`.\n    -   After the closing parens invoke `C-x C-e` to execute them.\n    -   *Warning!* Arguments are evaluated **before** the function is executed.\n    -   Only prefix invocations means we can use `-,+,*` in *names*\n        since `(f+*- a b)` is parsed as applying function `f+*-` to arguments `a, b`.\n\n        E.g., `(1+ 42) → 43` using function *named* `1+` \u0026#x2014;the ‘successor function’.\n\n-   Function definition:\n\n        ;; “de”fine “fun”ctions\n        (defun my-fun (arg₀ arg₁ … argₖ)         ;; header, signature\n          \"This functions performs task …\"       ;; documentation, optional\n          …sequence of instructions to perform… ) ;; body\n\n    -   The return value of the function is the result of the last expression executed.\n    -   The documentation string may indicate the return type, among other things.\n\n-   Anonymous functions: `(lambda (arg₀ … argₖ) bodyHere)`.\n\n    \u003cdiv class=\"parallel\"\u003e\n        ;; make then way later invoke\n        (setq my-f (lambda (x y) (+ x y)))\n        (funcall my-f 1 2) ;; ⇒ 3\n        ;; (my-f 1 2) ;; invalid!\n        (funcall my-f 1 2) ;; ⇒ 3\n\n    \\columnbreak\n\n        ;; make and immediately invoke\n        (funcall (lambda (x y) (+ x y)) 1 2)\n\n         ;; works, but is deprecated\n        ((lambda (x y) (+ x y)) 1 2)\n\n    \u003c/div\u003e\n\nFunctions are first-class values *but* variables and functions have **separate namespaces**\n\u0026#x2014;“Elisp is a Lisp-2 Language”.\nThe function represented by the name *g* is obtained\n  by the call `(function g)`, which is also denoted `#'g`.\n  The sharp quote behaves like the usual quote but causes its argument to be compiled.\n  `lambda` is a macro that calls `function` and so there is rarely any need to quote lambdas.\n  If `h` is a variable referring to a function, then `(funcall h x₀ … xₙ)`\n  calls that function on arguments `xᵢ`.\n\n\u003ctable border=\"2\" cellspacing=\"0\" cellpadding=\"6\" rules=\"groups\" frame=\"hsides\"\u003e\n\n\n\u003ccolgroup\u003e\n\u003ccol  class=\"org-left\" /\u003e\n\u003c/colgroup\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd class=\"org-left\"\u003e`(apply 'g x₀…xₖ '(xₖ…xₙ)) ≈ (funcall #'g x₀…xₙ) ≈ (g x₀…xₙ)`\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\n    ;; Recursion with the ‘tri’angle numbers: tri n = Σⁿᵢ₌₀ i.\n    (defun tri (f n) (if (\u003c= n 0) 0 (+ (funcall f n) (tri f (- n 1)))))\n    (tri #'identity 100)           ;; ⇒ 5050\n    (tri (lambda (x) (/ x 2)) 100) ;; ⇒ 2500\n\n    ;; Run “C-h o tri” to see TWO items! Location determines dispatch.\n    (setq tri 100) (tri #'identity tri)      ;; ⇒ 5050\n    (setq tri (lambda (x) x)) (tri tri 100)  ;; ⇒ 5050\n\n-   **→:** Use `funcall` or `apply` to call functions bound to variables.\n-   **→:** Refer to functions outside of function calls by using a sharp quote, `#'`.\n\nWe may have positional `optional` arguments, or optional but named arguments\n\u0026#x2014;for which position does not matter.\nUn-supplied optional arguments are bound to `nil`.\n\n\u003cdiv class=\"parallel\"\u003e\n    (cl-defun f (a \u0026optional b (c 5))\n       (format \"%s %s %s\" a b c))\n\n    (f 'a)       ;; ⇒ \"a nil 5\"\n    (f 'a 'b)    ;; ⇒ \"a b 5\"\n    (f 'a 'b 'c) ;; ⇒ \"a b c\"\n\n    (cl-defun g (a \u0026key (b 'nice) c)\n       (format \"%s %s %s\" a b c))\n\n    (g 1 :c 3 :b 2) ;; ⇒ \"1 2 3\"\n    (g 1 :c 3)      ;; ⇒ \"1 nice 3\"\n\n\u003c/div\u003e\n\nKeywords begin with a colon, `:k` is a constant whose value is `:k`.\n\n\n\u003ca id=\"orge624d54\"\u003e\u003c/a\u003e\n\n# Quotes, Quasi-Quotes, and Unquotes\n\nQuotes: `'x` refers to the *name* rather than the *value* of `x`.\n\n-   This is superficially similar to pointers:\n    Given `int *x = …`, `x` is the name (address)\n    whereas `*x` is the value.\n-   The quote simply forbids evaluation; it means *take it literally as you see it*\n    rather than looking up the definition and evaluating.\n-   Note: `'x ≈ (quote x)`.\n\nAkin to English, quoting a word refers to the word and not what it denotes.\n\nThis lets us treat *code* as *data*! E.g., `'(+ 1 2)` evaluates to `(+ 1 2)`, a function call,\n    not the value `3`! Another example, `*` is code but `'*`\n    is data, and so `(funcall '* 2 4)` yields 8.\n\n*Elisp expressions are either atoms or function application \u0026#x2013;nothing else!*\n\n‘Atoms’ are the simplest objects in Elisp: They evaluate to themselves; \\newline\ne.g., `5, \"a\", 2.78, 'hello, [1 \"two\" three]`.\n\nAn English sentence is a list of words; if we want to make a sentence where some of\nthe words are parameters, then we use a quasi-quote \u0026#x2013;it's like a quote, but allows\nus to evaluate data if we prefix it with a comma. It's usually the case that the\nquasi-quoted sentence happens to be a function call! In which case, we use `eval`\nwhich executes code that is in data form; i.e., is quoted.\n\nMacros are essentially functions that return sentences, lists, which may happen to\ncontain code.\n\n\u003cdiv class=\"parallel\"\u003e\n    ;; Quotes / sentences / data\n    '(I am a sentence)\n    '(+ 1 (+ 1 1))\n\n    ;; Executing data as code\n    (eval '(+ 1 (+ 1 1)))  ;; ⇒ 3\n\n    (setq name \"Jasim\")\n\n    ;; Quasi-quotes: Sentences with a\n    ;; computation, code, in them.\n    `(Hello ,name and welcome)\n    `(+ 1 ,(+ 1 1))  ;; ⇒ '(+ 1 2)\n\n\u003c/div\u003e\n\nAs the final example shows, Lisp treats data and code interchangeably.\nA language that uses the same structure to store data and code is called ‘homoiconic’.\n\n\n\u003ca id=\"orgdb68da1\"\u003e\u003c/a\u003e\n\n# Reads\n\n-   [How to Learn Emacs: A Hand-drawn One-pager for Beginners / A visual tutorial](http://sachachua.com/blog/wp-content/uploads/2013/05/How-to-Learn-Emacs-v2-Large.png)\n-   [Learn Emacs Lisp in 15 minutes](https://emacs-doctor.com/learn-emacs-lisp-in-15-minutes.html) \u0026#x2014; \u003chttps://learnxinyminutes.com/\u003e\n-   [An Introduction to Programming in Emacs Lisp](https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html#Top)  [Land of Lisp](http://landoflisp.com/)\n-   [GNU Emacs Lisp Reference Manual](https://www.gnu.org/software/emacs/manual/html_node/elisp/index.html#Top)\n\n\n\u003ca id=\"org943c427\"\u003e\u003c/a\u003e\n\n# Variables\n\n-   Global Variables, Create \u0026 Update: `(setq name value)`.\n\n    -   Generally: `(setq name₀ value₀ ⋯ nameₖ valueₖ)`.\n\n    Use `devfar` for global variables since it\n    permits a documentation string \u0026#x2013;but updates must be performed with `setq`.\n    E.g., `(defvar my-x 14 \"my cool thing\")`.\n\n    \u003ctable border=\"2\" cellspacing=\"0\" cellpadding=\"6\" rules=\"groups\" frame=\"hsides\"\u003e\n\n\n    \u003ccolgroup\u003e\n    \u003ccol  class=\"org-left\" /\u003e\n    \u003c/colgroup\u003e\n    \u003ctbody\u003e\n    \u003ctr\u003e\n    \u003ctd class=\"org-left\"\u003e`(setq x y) ≈ (set (quote x) y)`\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003c/tbody\u003e\n    \u003c/table\u003e\n\n    Variables are assigned with `set`,\n    which takes a quoted identifier, so that it's not evaluated,\n    and a value to associate to that variable. “set quoted”, `setq`,\n    avoids the hassle of quoting the name.\n    More generally, `(set sym v)` assigns the *value of* `sym` to have the value `v`.\n\n-   Local Scope: `(let ((name₀ val₀) … (nameₖ valₖ)) bodyBlock)`.\n    -   `let*` permits later bindings to refer to earlier ones.\n    -   The simpler `let` indicates to the reader that there are no dependencies between the variables.\n    -   let ≈ parallel; let\\* ≈ sequential.\n    -   Local functions declared with `flet` and `flet*`; e.g.,\n        `(flet ((go (x) (+ 2 x))) (go 3))`.\n\n-   Any sequence of symbols is a valid identifier, including `x, x-y/z, --\u003c\u003c==\u003e\u003e--`\n    and even `∀∃`. Elisp names are case sensitive.\n\n-   Elisp is dynamically scoped: The caller's stack is accessible by default!\n\n        (defun woah ()\n          \"If any caller has a local ‘work’, they're in for a nasty bug\n           from me! Moreover, they better have ‘a’ defined in scope!\"\n          (setq work (* a 111))) ;; Benefit: Variable-based scoped configuration.\n\n        (defun add-one (x)\n          \"Just adding one to input, innocently calling library method ‘woah’.\"\n          (let ((work (+ 1 x)) (a 6))\n            (woah) ;; May change ‘work’ or access ‘a’!\n            work\n          )\n        )\n\n        ;; (add-one 2) ⇒ 666\n\n\n\u003ca id=\"orgbc87d9e\"\u003e\u003c/a\u003e\n\n# Lists and List-Like Structures\n\n-   Produce a syntactic, un-evaluated list, we use the single quote:\n    `'(1 2 3)`.\n\n-   Construction: `(cons 'x₀ '(x₁ … xₖ)) → (x₀ x₁ … xₖ)`.\n\n-   Head, or *contents of the address part of the register*:\n    `(car '(x₀ x₁ … xₖ)) → x₀`.\n\n-   Tail, or *contents of the decrement part of the register*:\n    `(cdr '(x₀ x₁ … xₖ)) → (x₁ … xₖ)`.\n\nE.g., `(cons 1 (cons \"a\" (cons 'nice nil))) ≈ (list 1 \"a\" 'nice) ≈ '(1 \"a\" nice)`.\n\nSince variables refer to literals and functions have lambdas as literals, we\ncan produce forms that take functions as arguments. E.g., the standard `mapcar`\nmay be construed:\n\n    (defun my-mapcar (f xs)\n      (if (null xs) xs\n       (cons (funcall f (car xs)) (my-mapcar f (cdr xs)))))\n\n    (my-mapcar (lambda (x) (* 2 x)) '(0 1 2 3 4 5)) ;; ⇒ (0 2 4 6 8 10)\n    (my-mapcar 'upcase '(\"a\" \"b\" \"cat\")) ;; ⇒ (\"A\" \"B\" \"CAT\")\n\nPairs: `(x . y) ≈ (cons x y)`.\n\nAn association list, or alist, is a list formed of such pairs.\nThey're useful for any changeable collection of key-value pairs.\nThe `assoc` function takes a key and an alist and returns the first pair\nhaving that key. In the end, alists are just lists.\n\n(Rose) Trees in lisp are easily formed as lists of lists where each inner\n   list is of length 2:\n   The first symbol is the parent node and the second is the list of children.\n\nLists are formed by chains of cons cells, so getting and setting are very slow;\nlikewise for alists. If performance is desired, one uses arrays and hash tables,\nrespectively, instead. In particular, the performance of arrays and hash tables always\nrequires a constant amount of time whereas the performance of lists and alists grows in\nproportion with their lengths.\n\nHowever, the size of an array is fixed \u0026#x2014;it cannot change and thus grow\u0026#x2014; and hash\ntables have a lookup cost as well as issues with \"hash collisions\". Their use is worth\nit for large amounts of data, otherwise lists are the way to go.\n\nAn [array](https://www.gnu.org/software/emacs/manual/html_node/elisp/Arrays.html) is created like a list but using [only square brackets] with getter `(aref arr index)`.\n\nA hash table is created with `(make-hash-table)` with getter `(gethash key table)`.\n\nWhat if you look up a key and get `nil`, is there no value for that key or is the value\n`nil`? `gethash` takes a final, optional, argument which is the value to return when the\nkey is not found; it is `nil` by default.\n\n\n\u003ca id=\"org8ccfbc7\"\u003e\u003c/a\u003e\n\n# Generic Setters\n\nSince everything is a list in lisp, if `G` is a way to get a value from variable `x`, then `(setf G e)` updates `x` so that the location `G` now refers to element `e`.\nHence, once you have a getter `G` you freely obtain a setter `(setf G ⋯)`.\n\n    ;; Element update\n    (setq x '(0 1 2 3))    ;; x ⇒ '(0 1 2     3)\n    (setf (nth 2 x) 'nice) ;; x ⇒ '(0 1 'nice 3)\n\n    ;; Circular list\n    (setq y '(a b c))   ;; y ⇒ '(a b c)\n    (setf (cdddr y) y)  ;; y ⇒ '(a b c a b . #2)\n    ;; “#2” means repeat from index 2.\n    (nth 99 y) ;; ⇒ a\n\n\n\n\u003ca id=\"org71dcb45\"\u003e\u003c/a\u003e\n\n# Records\n\nIf we want to keep a list of related properties in a list, then we have to remember\nwhich position keeps track of which item and may write helper functions to keep track\nof this. Instead we could use a structure.\n\n    (defstruct X \"Record with fields/slots fᵢ having defaults dᵢ\"\n      (f₀ d₀) ⋯ (fₖ dₖ))\n\n    ;; Automatic constructor is “make-X” with keyword parameters for\n    ;; initialising any subset of the fields!\n    ;; Hence (expt 2 (1+ k)) kinds of possible constructor combinations!\n    (make-X :f₀ val₀ :f₁ val₁ ⋯ :fₖ valₖ) ;; Any, or all, fᵢ may be omitted\n\n    ;; Automatic runtime predicate for the new type.\n    (X-p (make-X)) ;; ⇒ true\n    (X-p 'nope)    ;; ⇒ nil\n\n    ;; Field accessors “X-fᵢ” take an X record and yield its value.\n\n    ;; Field update: (setf (X-fᵢ x) valᵢ)\n\n    (defstruct book\n      title  (year  0))\n\n    (setq ladm (make-book :title \"Logical Approach to Discrete Math\" :year 1993))\n    (book-title ladm) ;; ⇒ \"Logical Approach to Discrete Math\"\n    (setf (book-title ladm) \"LADM\")\n    (book-title ladm) ;; ⇒ \"LADM\"\n\nAdvanced OOP constructs can be found within the CLOS, Common Lisp Object System;\nwhich is also used as a research tool for studying OOP ideas.\n\n\n\u003ca id=\"org9c71fdf\"\u003e\u003c/a\u003e\n\n# Block of Code\n\nUse the `progn` function to treat multiple expressions as a single expression. E.g.,\n\n    (progn\n      (message \"hello\")\n      (setq x  (if (\u003c 2 3) 'two-less-than-3))\n      (sleep-for 0 500)\n      (message (format \"%s\" x))\n      (sleep-for 0 500)\n      23    ;; Explicit return value\n    )\n\nThis' like curly-braces in C or Java. The difference is that the last expression is considered\nthe ‘return value’ of the block.\n\nHerein, a ‘block’ is a number of sequential expressions which needn't be wrapped with a `progn` form.\n\n-   Lazy conjunction and disjunction:\n\n    -   Perform multiple statements but stop when any of them fails, returns `nil`: `(and s₀ s₁ … sₖ)`.\n        -   Maybe monad!\n    -   Perform multiple statements until one of them succeeds, returns non-`nil`: `(or s₀ s₁ … sₖ)`.\n\n    We can coerce a statement `sᵢ` to returning non-`nil` as so: (`progn sᵢ t)`.\n    Likewise, coerce failure by `(progn sᵢ nil)`.\n\n-   Jumps, Control-flow transfer: Perform multiple statements and decide when and where you would like to stop. This' akin to C's `goto`'s; declare a label with `catch` and goto it with `throw`.\n\n    -   `(catch 'my-jump bodyBlock)` where the body may contain `(throw 'my-jump returnValue)`;\n\n    the value of the catch/throw is then `returnValue`.\n\n    -   Useful for when the `bodyBlock` is, say, a loop.\n        Then we may have multiple `catch`'s with different labels according to the nesting of loops.\n        -   Possibly informatively named throw symbol is `'break`.\n    -   Using name `'continue` for the throw symbol and having such a catch/throw as *the body of a loop*\n        gives the impression of continue-statements from Java.\n    -   Using name `'return` for the throw symbol and having such a catch/throw as the body of a function\n        definition gives the impression of, possibly multiple, return-statements from Java\n        \u0026#x2013;as well as ‘early exits’.\n    -   Simple law: `(catch 'it s₀ s₁ … sₖ (throw 'it r) sₖ₊₁ ⋯ sₖ₊ₙ) ≈ (progn s₀ s₁ ⋯ sₖ r)`.\n        -   Provided the `sᵢ` are simple function application forms.\n\n-   `and, or` can be thought of as instance of catch/throw, whence they are control flow\n    first and Boolean operations second.\n\n        (and s₀ ⋯ sₙ e)  ⇒  when all xᵢ are true, do e\n        (or  s₀ ⋯ sₙ e)  ⇒  when no xᵢ is true, do e\n\n\n\u003ca id=\"orgaa669ec\"\u003e\u003c/a\u003e\n\n# Conditionals\n\n-   Booleans: `nil`, the empty list `()`, is considered *false*, all else\n    is *true*.\n    -   Note: `nil ≈ () ≈ '() ≈ 'nil`.\n    -   (Deep structural) equality: `(equal x y)`.\n    -   Comparisons: As expected; e.g., `(\u003c= x y)` denotes *x ≤ y*.\n\n-   `(if condition thenExpr optionalElseBlock)`\n    -   Note: `(if x y) ≈ (if x y nil)`; \\newline better: `(when c thenBlock) ≈ (if c (progn thenBlock))`.\n    -   Note the else-clause is a ‘block’: Everything after the then-clause is considered to be part of it.\n    -   `(if xs ⋯)` means “if xs is nonempty then ⋯” is akin to C style idioms on\n        linked lists.\n\n\u003cdiv class=\"parallel\"\u003e\n    (cond\n      (test₀\n        actionBlock₀)\n      (test₁\n        actionBlock₁)\n      …\n      (t                    ;; optional\n        defaultActionBlock))\n\n\\columnbreak\n\n    ;; pattern matching on any type\n    (defun go (x)\n      (pcase x\n        ('bob 1972)\n        (`(,a ,_ ,c) (+ a c))\n        (otherwise \"Shucks!\")))\n\n    (go 'bob)     ;; ⇒ 1972\n    (go '(1 2 3)) ;; ⇒ 4\n    (go 'hallo)   ;; \"Shucks!\"\n\n\u003c/div\u003e\n\nAvoid nested if-then-else clauses by using a `cond` statement \u0026#x2013;a (lazy) generalisation\nof switch statements: It sequentially evaluates the expressions `testᵢ` and\nperforms only the action of the first true test; yielding `nil` when no tests are true.\nOr use [pattern matching](http://www.wilfred.me.uk/blog/2017/03/19/pattern-matching-in-emacs-lisp/); which even allows predicates in the case position ---`C-h o` ;-)\n\nHint: If you write a predicate, think of what else you can return besides `t`; such as\na witness to why you're returning truth \u0026#x2013;all non-nil values denote true after all.\nE.g., `(member e xs)` returns the sublist of `xs` that begins with `e`.\n\n\n\u003ca id=\"org45458fb\"\u003e\u003c/a\u003e\n\n# Loops\n\nLet's sum the first `100` numbers in 3 ways.\n\n\u003cdiv class=\"parallel\"\u003e\n    (let ((n 100) (i 0) (sum 0))\n      (while (\u003c= i n)\n        (incf sum i) (incf i))\n        (message (format \"sum: %s\" sum)))\n\n\\columnbreak\n\n\u003ctable border=\"2\" cellspacing=\"0\" cellpadding=\"6\" rules=\"groups\" frame=\"hsides\"\u003e\n\n\n\u003ccolgroup\u003e\n\u003ccol  class=\"org-left\" /\u003e\n\n\u003ccol  class=\"org-left\" /\u003e\n\u003c/colgroup\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd class=\"org-left\"\u003e\u003cspan class=\"underline\"\u003eC\u003c/span\u003e\u003c/td\u003e\n\u003ctd class=\"org-left\"\u003e\u003cspan class=\"underline\"\u003eElisp\u003c/span\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\n\n\u003ctr\u003e\n\u003ctd class=\"org-left\"\u003e`x += y`\u003c/td\u003e\n\u003ctd class=\"org-left\"\u003e`(incf x y)`\u003c/td\u003e\n\u003c/tr\u003e\n\n\n\u003ctr\u003e\n\u003ctd class=\"org-left\"\u003e`x -= y`\u003c/td\u003e\n\u003ctd class=\"org-left\"\u003e`(decf x y)`\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\n`y` is optional, and is 1 by default.\n\n\u003c/div\u003e\n\n    ;; Repeat body n times, where i is current iteration.\n    (let ((result 0) (n 100))\n      (dotimes (i (1+ n) result) (incf result i)))\n\n    ;; A for-each loop: Iterate through the list [0..100].\n    (let ((result 0) (mylist (number-sequence 0 100)))\n      (dolist (e mylist result) (incf result e)))\n\nIn both loops, `result` is optional and defaults to nil.\nIt is the return value of the loop expression.\n\n\u003ctable border=\"2\" cellspacing=\"0\" cellpadding=\"6\" rules=\"groups\" frame=\"hsides\"\u003e\n\n\n\u003ccolgroup\u003e\n\u003ccol  class=\"org-left\" /\u003e\n\u003c/colgroup\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd class=\"org-left\"\u003e**Example of Above Constructs**\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\n    (defun my/cool-function (N D)\n      \"Sum the numbers 0..N that are not divisible by D\"\n      (catch 'return\n        (when (\u003c N 0) (throw 'return 0)) ;; early exit\n        (let ((counter 0) (sum 0))\n          (catch 'break\n        (while 'true\n          (catch 'continue\n            (incf counter)\n            (cond ((equal counter N)       (throw 'break sum   ))\n               ((zerop (% counter D))  (throw 'continue nil))\n               ('otherwise             (incf sum counter   )) )))))))\n\n    (my/cool-function  100 3)  ;; ⇒ 3267\n    (my/cool-function  100 5)  ;; ⇒ 4000\n    (my/cool-function -100 7)  ;; ⇒ 0\n\nThe special [loop](http://www.gigamonkeys.com/book/loop-for-black-belts.html) construct provides immensely many options to form\nnearly any kind of imperative loop. E.g., Python-style ‘downfrom’ for-loops\nand Java do-while loops. I personally prefer functional programming, so wont\nlook into this much.\n\n\n\u003ca id=\"orgeb7a6f7\"\u003e\u003c/a\u003e\n\n# Exception Handling\n\nWe can attempt a dangerous clause and catch a possible exceptional case\n\u0026#x2013;below we do not do so via `nil`\u0026#x2013; for which we have an associated handler.\n\n    (condition-case nil attemptClause (error recoveryBody))\n\n      (ignore-errors attemptBody)\n    ≈ (condition-case nil (progn attemptBody) (error nil))\n\n    (ignore-errors (+ 1 \"nope\")) ;; ⇒ nil\n\n\n\u003ca id=\"org825332f\"\u003e\u003c/a\u003e\n\n# Types \u0026 Overloading\n\nSince Lisp is dynamically typed, a variable can have any kind of data, possibly\ndifferent kinds if data at different times in running a program.\nWe can use `type-of` to get the type of a given value; suffixing that with `p`\ngives the associated predicate; \\newline e.g., `function ↦ functionp`.\n\n    ;; Difficult to maintain as more types are added.\n    (defun sad-add (a b)\n      (if (and (numberp a) (numberp b))\n          (+ a b)\n          (format \"%s + %s\" a b))\n    )\n\n    (sad-add 2 3)       ;; ⇒ 5\n    (sad-add 'nice \"3\") ;; ⇒ \"nice + 3\"\n\n    ;; Better: Seperation of concerns.\n    ;;\n    (cl-defmethod add ((a number) (b number)) (+ a b))      ;; number types\n    (cl-defmethod add ((a t) (b t)) (format \"%s + %s\" a b)) ;; catchall types\n\n    (add 2 3)       ;; ⇒ 5\n    (add 'nice \"3\") ;; ⇒ \"nice + 3\"\n\nWhile list specific functions like list-length and mapcar may be more efficient than\ngeneric functions, which require extra type checking, the generic ones are easier to\nremember. The following generic functions work on lists, arrays, and strings:\n\n-   `find-if`, gets first value satisfying a predicate.\n-   `count`, finds how often an element appears in a sequence\n-   `position`, finds the index of a given element.\n-   `some`, check if any element satisfies a given predicate\n-   `every`, check if every element satisfies the given predicate\n-   `reduce`, takes a binary operation and a sequence and mimics a for-loop.\n    Use keyword `:initial-value` to specify the starting value, otherwise use head of\n    sequence.\n-   `sum`, add all numbers; crash for strings.\n-   `length, subseq, sort`.\n\n[dash](https://github.com/magnars/dash.el) is a modern list library for Emacs that uses Haskell-like names for list operations ;-)\nLikewise, [s](https://github.com/magnars/s.el) is a useful Emacs string manipulation library.\n\nIn-fact, we can [write Emacs extensions using Haskell directly](https://github.com/knupfer/haskell-emacs).\n\n\n\n\u003ca id=\"orgc487ae3\"\u003e\u003c/a\u003e\n\n# Macros\n\nMacros let us add new syntax, like `let1` for single lets:\n\n\u003cdiv class=\"parallel\"\u003e\n    ;; Noisy parens!\n    (let ((x \"5\")) (message x))\n\n    ;; Better.\n    (let1 x \"5\" (message x))\n\n    ;; How?\n    (defmacro let1 (var val \u0026rest body)\n     `(let ((,var ,val)) ,@body))\n\n    ;; What does it look like?\n    (macroexpand\n      '(let1 x \"5\" (message x)))\n    ;; ⇒ (let ((x 5)) (message x))\n\n\\columnbreak\n\n    ;; No progn; (first x y z) ≈ x\n    (defmacro first (\u0026rest body)\n     (car `,@body))\n\n    ;; Need to use “progn”!\n    (defmacro not-first (\u0026rest body)\n     `(progn ,@(cdr `,@body)))\n\n    (macroexpand '(not-first x y z))\n    ;; `,@body       ⇒ (x y z)\n    ;; (cdr `,@body) ⇒ (y z)\n    ;; `(progn ,@(cdr `,@body))\n    ;;        ⇒ (progn y z)\n\n\u003c/div\u003e\n\n1.  Certain problems are elegantly solved specific language constructs;\n    e.g., list operations are generally best defined by pattern matching.\n\n2.  Macros let us *make* the best way to solve a problem when our language does\n    not give it to us.\n\n3.  Macro expansion happens before runtime, function execution, and so the\n    arguments passed to a macro will contain raw source code.\n\n    [Backquotes](http://www.lispworks.com/documentation/HyperSpec/Body/02_df.htm) let us use the comma to cause the actual variable *names*\n    and *values* to be used \u0026#x2013;e.g., `x` is a ‘meta-variable’ and its value, `,x`,\n    refers to a real variable or value.\n\n    The `\u0026rest` marker allows us to have multiple statements at the end of the macro:\n    The macro expander provides all remaining expressions in the macro as a list,\n    the contents of which may be inserted in place, not as a list, using the\n    [ `,@` splice comma](https://www.gnu.org/software/emacs/manual/html_node/elisp/Backquote.html)  \u0026#x2013;we need to ensure there's a `progn`.\n\n    Use list elements in-place:\n\n    \u003ctable border=\"2\" cellspacing=\"0\" cellpadding=\"6\" rules=\"groups\" frame=\"hsides\"\u003e\n\n\n    \u003ccolgroup\u003e\n    \u003ccol  class=\"org-left\" /\u003e\n    \u003c/colgroup\u003e\n    \u003ctbody\u003e\n    \u003ctr\u003e\n    \u003ctd class=\"org-left\"\u003e`` `(pre ,@(list s₀ ⋯ sₙ) post) ≈ `(pre s₀ ⋯ sₙ post) ``\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003c/tbody\u003e\n    \u003c/table\u003e\n\n-   `macroexpand` takes *code* and expands any macros in it. It's useful in debugging macros.\n    The above ‘equations’ can be checked by running `macroexpand`; \\newline e.g.,\n    `(when c s₀ ⋯ sₙ) ≈ (if c (progn s₀ ⋯ sₙ) nil)` holds since:\n\n        (macroexpand '(when c s₀ ⋯ sₙ)) ;; ⇒ (if c (progn s₀ ⋯ sₙ))\n\n-   If `var` is an argument to a macro where `,var` occurs multiple times, then since\n    arguments to macros are raw source code, each occurrence of `,var` is an execution of the\n    code referenced by `var`.\n\n    Avoid such repeated execution by using a `let` to capture the result, call it `res`, once\n    and use the `res` in each use site.\n\n    Now we've made use of the name `res` and our users cannot use that name correctly.\n    Avoid such *unintended* capture by using `gensym` to provide us with a globally unique\n    name which is bound to a variable, say `r`, then we bind the result of executing `var`\n    to the fresh name `,r`.\n\n    Whence: `` `(⋯,var⋯,var⋯) ``\n\n      ``⇒ (let ((r (gensym))) `(let ((,r ,var)) ⋯,r⋯,r⋯))``.\n\n    Note that the name `r` is outside the backquote; it is part of code that is run\n    at macro expansion time, not runtime. The value of the final `let` is then the backquoted\n    matter, which makes *no* reference to `r`, but instead makes use of the name it\n    refers to, `,r`. Neato!\n\n    Ex., remove repeated execution from ``(defmacro twice (var) `(list ,var ,var))``.\n\n-   Test that you don't have accidentally variable capture by passing in an insert\n    statement and see how many times insertions are made.\n\n-   Macros that *intentionally* use variable capture as a feature, rather than a bug,\n    to provide names available in the macro body are called ‘anaphoric macros’.\n\n    E.g., `(split list no yes)` provides the names `head, tail` in the `yes` body\n    to refer to the head and tail of the given `list`, say via a `let`, but not so in the\n    `no` argument for when `list` is empty. Whence, elegant pattern matching on lists.\n\n    Exercise: Define `split`.\n\n\\vfill\n\n\n\u003ca id=\"org7ece87e\"\u003e\u003c/a\u003e\n\n# `read` and `print`\n\n‘Reading’ means parsing an expression in textual form and producing a lisp object.\nE.g., this is a way to load a lisp file. ‘Printing’ a lisp object mean producing\na textual representation. These operations, in lisp, are mostly inverse.\n\nThe `read-from-string` command works just like the `read` command, but\nlets us read a lisp object from a string instead of directly from the console.\n\n    (defun sum-two ()\n      (let (fst snd)\n        (setq fst (read))\n        (setq snd (read))\n        (+ (eval fst) (eval snd))\n      )\n    )\n\n    ;; Run (sum-two) with inputs (+ 1 2) and (* 3 4)  ;-)\n\nLisp makes writing a REPL astonishingly easy: “Loop as follows:\nPrint the result of evaluating what is read at the prompt.”\n\n    (loop (print (eval (read))))  ;; Beautiful ♥‿♥\n\n-   `loop` merely loops forever.\n\nThe `print` and `read` commands work on all kinds of data, such as lists of data\n  structures. Hence, we must use quotes if we want to read a string rather than a\n  symbol, for example.\n\nA major problem with this REPL is that `eval` executes any, potentially malicious,\nLisp command entered by the user. Ideally one checks the read lisp object is\nsafe \u0026#x2014;say, it is one of some allowable commands\u0026#x2014; and only then evaluates it.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falhassy%2Felispcheatsheet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falhassy%2Felispcheatsheet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falhassy%2Felispcheatsheet/lists"}