├── .gitmodules ├── CheatSheet.org ├── CheatSheet.pdf ├── README.md └── _config.yml /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "CheatSheet"] 2 | path = CheatSheet 3 | url = https://github.com/alhassy/CheatSheet.git 4 | -------------------------------------------------------------------------------- /CheatSheet.org: -------------------------------------------------------------------------------- 1 | # f7 preview changes 2 | # (local-set-key (kbd "") (lambda () (interactive) (async-shell-command (concat "open " (org-latex-export-to-pdf))))) 3 | 4 | :Not_ideal: 5 | #+BEGIN_SRC emacs-lisp 6 | (setq org-latex-listings 'minted 7 | org-latex-packages-alist '(("" "minted")) 8 | org-latex-pdf-process 9 | '("pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f" 10 | "biber %b" 11 | "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f" 12 | "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f") 13 | ) 14 | #+END_SRC 15 | :End: 16 | 17 | * Header :ignore: 18 | #+TITLE: Elisp Reference Sheet 19 | # SUBTITLE: Cheat Sheet Template 20 | # DATE: << Winter 2019 >> 21 | # When we don't provide a date, one is provided for us. 22 | #+MACRO: URL https://github.com/alhassy/ElispCheatSheet 23 | #+MACRO: ShowURL @@latex:{\tiny\hspace{6em}\url{ {{{URL}}} } }@@ 24 | #+AUTHOR: [[http://www.cas.mcmaster.ca/~alhassm/][Musa Al-hassy]] {{{ShowURL}}} 25 | #+EMAIL: alhassy@gmail.com 26 | #+DESCRIPTION: This document is written by Musa Al-hassy for his learning in the Winter of 2019. 27 | #+STARTUP: hideblocks 28 | #+STARTUP: overview 29 | #+TODO: TODO | spacing 30 | #+OPTIONS: d:nil 31 | #+INCLUDE: CheatSheet/CheatSheetSetup.org 32 | 33 | * LaTeX Setup :ignore: 34 | # Can be obtained from: https://github.com/alhassy/MyUnicodeSymbols 35 | # 36 | #+LATEX_HEADER: \usepackage{/Users/musa/MyUnicodeSymbols/MyUnicodeSymbols} 37 | 38 | #+NAME: parallel enviro 39 | #+BEGIN_EXPORT latex 40 | % \setlength{\columnseprule}{2pt} 41 | 42 | \renewenvironment{parallel}[1][2] % one argument, whose default value is literal `2`. 43 | { 44 | \setlength{\columnseprule}{2pt} 45 | \begin{minipage}[t]{\linewidth} % width of minipage is 100% times of \linewidth 46 | \begin{multicols}{#1} % default is `2` 47 | } 48 | { 49 | \setlength{\columnseprule}{0pt} 50 | \end{multicols} 51 | \end{minipage} 52 | } 53 | #+END_EXPORT 54 | 55 | # Removing the red box that appears in "minted" when using unicode. 56 | # Src: https://tex.stackexchange.com/questions/343494/minted-red-box-around-greek-characters 57 | # 58 | #+LATEX_HEADER: \makeatletter 59 | #+LATEX_HEADER: \AtBeginEnvironment{minted}{\dontdofcolorbox} 60 | #+LATEX_HEADER: \def\dontdofcolorbox{\renewcommand\fcolorbox[4][]{##4}} 61 | #+LATEX_HEADER: \makeatother 62 | 63 | * Intro :ignore: 64 | /Everything is a list!/ 65 | 66 | - To find out more about ~name~ execute ~(describe-symbol 'name)~! 67 | * After the closing parens invoke ~C-x C-e~ to evaluate. 68 | - To find out more about a key press, execute ~C-h k~ then the key press. 69 | - To find out more about the current mode you're in, execute ~C-h m~ or 70 | ~describe-mode~. Essentially a comprehensive yet terse reference is provided. 71 | :Examples: 72 | (describe-symbol 'just-one-space) 73 | (describe-symbol 'eldoc-mode) 74 | (describe-symbol 'describe-symbol) 75 | :End: 76 | 77 | * Functions 78 | 79 | #+latex: {\color{white}.}\vspace{-1em} 80 | + Function invocation: ~(f x₀ x₁ … xₙ)~. E.g., ~(+ 3 4)~ or ~(message "hello")~. 81 | - After the closing parens invoke ~C-x C-e~ to execute them. 82 | - /Warning!/ Arguments are evaluated *before* the function is executed. 83 | - Only prefix invocations means we can use ~-,+,*~ in /names/ 84 | since ~(f+*- a b)~ is parsed as applying function ~f+*-~ to arguments ~a, b~. 85 | # Having infix notation, as in “a - b”, is what renders names “a-b” 86 | # from being parsed correctly. Lisp does not make use of infix names, 87 | # so this is a non-issue. Interestingly Agda allows +-* in names and infix! 88 | 89 | E.g., ~(1+ 42) → 43~ using function /named/ ~1+~ ---the ‘successor function’. 90 | 91 | + Function definition: 92 | #+BEGIN_SRC elisp 93 | ;; “de”fine “fun”ctions 94 | (defun my-fun (arg₀ arg₁ … argₖ) ;; header, signature 95 | "This functions performs task …" ;; documentation, optional 96 | …sequence of instructions to perform… ) ;; body 97 | #+END_SRC 98 | 99 | - The return value of the function is the result of the last expression executed. 100 | - The documentation string may indicate the return type, among other things. 101 | 102 | + Anonymous functions: ~(lambda (arg₀ … argₖ) bodyHere)~. 103 | # 104 | #+begin_parallel org 105 | #+BEGIN_SRC elisp 106 | ;; make then way later invoke 107 | (setq my-f (lambda (x y) (+ x y))) 108 | (funcall my-f 1 2) ;; ⇒ 3 109 | ;; (my-f 1 2) ;; invalid! 110 | (funcall my-f 1 2) ;; ⇒ 3 111 | #+END_SRC 112 | \columnbreak 113 | #+BEGIN_SRC elisp 114 | ;; make and immediately invoke 115 | (funcall (lambda (x y) (+ x y)) 1 2) 116 | 117 | ;; works, but is deprecated 118 | ((lambda (x y) (+ x y)) 1 2) 119 | #+END_SRC 120 | #+end_parallel 121 | 122 | #+latex: \vspace{-1em} 123 | # The last one is invalid since ~(f x0 … xk)~ is only meaningful for functions ~f~ formed using ~defun~. 124 | # More honestly, Elisp has distinct namespaces for functions and variables. 125 | 126 | :Deprecated_form: 127 | ;; make and immediately invoke 128 | ((lambda (x y) (message (format "x, y ≈ %s, %s" x y))) 1 2) 129 | 130 | https://www.gnu.org/software/emacs/manual/html_node/elisp/Function-Indirection.html 131 | 132 | :End: 133 | 134 | :To_investigate_further: 135 | #+latex: \room 136 | Indeed, ~(defun f (x₀ … xₖ) body) ≈ (fset 'f (lambda (x₀ … xₖ) body))~. 137 | - Using ~fset~, with quoted name, does not require using ~funcall~. 138 | 139 | (insert (format "\n %s" (macroexpand '(defun f (xs) body)))) 140 | (defalias (quote f) (function (lambda (xs) body))) 141 | :End: 142 | 143 | #+latex: \room 144 | Functions are first-class values /but/ variables and functions have *separate namespaces* 145 | ---“Elisp is a Lisp-2 Language”. 146 | The function represented by the name /g/ is obtained 147 | by the call ~(function g)~, which is also denoted ~#'g~. 148 | The sharp quote behaves like the usual quote but causes its argument to be compiled. 149 | ~lambda~ is a macro that calls ~function~ and so there is rarely any need to quote lambdas. 150 | If ~h~ is a variable referring to a function, then ~(funcall h x₀ … xₙ)~ 151 | calls that function on arguments ~xᵢ~. 152 | #+latex: \vspace{-0.4em} 153 | | ~(apply 'g x₀…xₖ '(xₖ…xₙ)) ≈ (funcall #'g x₀…xₙ) ≈ (g x₀…xₙ)~ | 154 | 155 | # “lambda” is actually a macro! 156 | # (macroexpand '(lambda (x) x)) 157 | 158 | :Try_it_out: 159 | #+BEGIN_SRC emacs-lisp 160 | (defun f (x) x) ;; identify function 161 | (funcall #'f 4) 162 | 163 | (defun fmap (h xs) (if xs (cons (funcall h (car xs)) (fmap h (cdr xs))) xs)) 164 | (fmap #'f '(1 2 3)) 165 | (fmap (lambda (x) (* 2 x)) '(1 2 3)) 166 | #+END_SRC 167 | :End: 168 | 169 | #+latex: {\color{white}.}\vspace{-2.4em} 170 | #+BEGIN_SRC emacs-lisp 171 | ;; Recursion with the ‘tri’angle numbers: tri n = Σⁿᵢ₌₀ i. 172 | (defun tri (f n) (if (<= n 0) 0 (+ (funcall f n) (tri f (- n 1))))) 173 | (tri #'identity 100) ;; ⇒ 5050 174 | (tri (lambda (x) (/ x 2)) 100) ;; ⇒ 2500 175 | 176 | ;; Run “C-h o tri” to see TWO items! Location determines dispatch. 177 | (setq tri 100) (tri #'identity tri) ;; ⇒ 5050 178 | (setq tri (lambda (x) x)) (tri tri 100) ;; ⇒ 5050 179 | #+END_SRC 180 | 181 | # ✓ 182 | #+latex: \vspace{-0.1em} 183 | + → :: Use ~funcall~ or ~apply~ to call functions bound to variables. 184 | + → :: Refer to functions outside of function calls by using a sharp quote, ~#'~. 185 | :Generally: 186 | #+BEGIN_SRC emacs-lisp 187 | ;; Generally: 188 | (f) ;; calls global function f 189 | (funcall f) ;; calls function bound to f 190 | (funcall #'f) ;; calls global function f 191 | #+END_SRC 192 | :End: 193 | 194 | :Old: 195 | + Recursion: 196 | ~(defun sum (f n) (if (<= n 0) 0 (+ (funcall f n) (sum f (- n 1)))))~ 197 | - Now ~(sum #'identity 100) → 5050~ and ~(sum (lambda (x) (/ x 2)) 100) → 2500~. 198 | 199 | + IO: ~(defun make-sum (n) (interactive "n") (message-box (format "%s" (sum n))))~ 200 | 201 | The ~interactive~ option means the value of ~n~ is queried to the user; e.g., 202 | enter 100 after executing ~(execute-extended-command "" "make-sum")~ or ~M-x make-sum~. 203 | 204 | In general ~interactive~ may take no arguments. 205 | The benefit is that the function can be executed using ~M-x~, 206 | and is then referred to as an interactive function. 207 | :End: 208 | 209 | We may have positional ~optional~ arguments, or optional but named arguments 210 | ---for which position does not matter. 211 | Un-supplied optional arguments are bound to ~nil~. 212 | # 213 | #+begin_parallel org 214 | #+BEGIN_SRC emacs-lisp 215 | (cl-defun f (a &optional b (c 5)) 216 | (format "%s %s %s" a b c)) 217 | 218 | (f 'a) ;; ⇒ "a nil 5" 219 | (f 'a 'b) ;; ⇒ "a b 5" 220 | (f 'a 'b 'c) ;; ⇒ "a b c" 221 | #+END_SRC 222 | 223 | #+BEGIN_SRC emacs-lisp 224 | (cl-defun g (a &key (b 'nice) c) 225 | (format "%s %s %s" a b c)) 226 | 227 | (g 1 :c 3 :b 2) ;; ⇒ "1 2 3" 228 | (g 1 :c 3) ;; ⇒ "1 nice 3" 229 | #+END_SRC 230 | #+end_parallel 231 | 232 | Keywords begin with a colon, ~:k~ is a constant whose value is ~:k~. 233 | 234 | ** TODO COMMENT more #' notes 235 | 236 | Three ways to define anonymous functions: ~function, lambda, #'~. 237 | 238 | 0. Plain quote, ~'~, tells the compiler to leave its argument as an expression, no further compilation is possible. 239 | 240 | 1. ~function~ behaves like ~quote~ but tells the compiler its argument is intended to be 241 | used as a function and should be compiled as such or converted into a closure. 242 | 243 | 2. ~lambda~ uses ~function~ as a subroutine to tell the compiler its argument is a function. 244 | 245 | 3. Thus, lambdas are self-quoting: Evaluating a form whose ~car~ is a ~lambda~ yields 246 | the form itself. ( It yields a closure under lexical binding. ) 247 | 248 | 4. The /sharp quote/ ~#'~ is short-hand for ~function~. 249 | 250 | #+begin_src emacs-lisp 251 | (lambda (x) x) 252 | ≈ #'(lambda (x) x) 253 | ≈ (function (lambda (x) x)) 254 | 255 | (macroexpand '#'(lambda (x) x) ;; ⇒ (function (lambda (x) x)) 256 | (macroexpand ''(lambda (x) x)) ;; ⇒ (function (lambda (x) x)) 257 | 258 | ''(lambda (x) x) ;; A list of items: Literal lambda, List (x), Literal x 259 | ;; TODO: MA: New adventure: When do we want to use quote-quote ? 260 | 261 | (funcall ''(lambda (x) (+ x 2)) 3) 262 | 263 | ;; Whence there is never any need to quote lambdas with either quote. 264 | #+end_src 265 | 266 | * TODO COMMENT interactive 267 | 268 | IO: In general ~interactive~ may take no arguments. 269 | It lets us use ~M-x~ to execute functions; 270 | here, this results in ~n~ being queried to the user. 271 | #+BEGIN_SRC emacs-lisp 272 | (defun double (n) (interactive "n") (message-box (format "%s" (* n 2)))) 273 | #+END_SRC 274 | 275 | * Quotes, Quasi-Quotes, and Unquotes 276 | 277 | Quotes: ~'x~ refers to the /name/ rather than the /value/ of ~x~. 278 | 279 | - This is superficially similar to pointers: 280 | Given ~int *x = …~, ~x~ is the name (address) 281 | whereas ~*x~ is the value. 282 | - The quote simply forbids evaluation; it means /take it literally as you see it/ 283 | rather than looking up the definition and evaluating. 284 | :TryItOut: 285 | #+BEGIN_SRC elisp 286 | (setq this 'hello) 287 | (setq that this) 288 | 289 | ;; this → hello 290 | ;; 'this → this 291 | ;; that → hello 292 | ;; 'that → that 293 | #+END_SRC 294 | :End: 295 | - Note: ~'x ≈ (quote x)~. 296 | 297 | :Try_it_out: 298 | #+BEGIN_SRC emacs-lisp 299 | 'x ≈ (quote x) 300 | (equal 'x (quote x)) ;; true 301 | 302 | ''x ≠ 'x 303 | (equal 'x ''x) ;; false 304 | #+END_SRC 305 | :End: 306 | 307 | #+latex: \room 308 | Akin to English, quoting a word refers to the word and not what it denotes. 309 | 310 | This lets us treat /code/ as /data/! E.g., ~'(+ 1 2)~ evaluates to ~(+ 1 2)~, a function call, 311 | not the value ~3~! Another example, ~*~ is code but ~'*~ 312 | is data, and so ~(funcall '* 2 4)~ yields 8. 313 | 314 | #+latex: \room 315 | 316 | /Elisp expressions are either atoms or function application --nothing else!/ 317 | 318 | ‘Atoms’ are the simplest objects in Elisp: They evaluate to themselves; \newline 319 | e.g., ~5, "a", 2.78, 'hello, [1 "two" three]~. 320 | :lambdas_are_not_literals: 321 | lambda's form function literals in that, e.g., 322 | ~(lambda (x) x)~ evaluates to itself. 323 | 324 | Read here: https://nullprogram.com/blog/2018/02/22/ 325 | :End: 326 | 327 | # Reddit/skeeto: There are lots of types in Emacs Lisp that are "atoms" but not actually atomic: vectors, records, hash tables, etc. 328 | 329 | 330 | #+latex: \room 331 | 332 | An English sentence is a list of words; if we want to make a sentence where some of 333 | the words are parameters, then we use a quasi-quote --it's like a quote, but allows 334 | us to evaluate data if we prefix it with a comma. It's usually the case that the 335 | quasi-quoted sentence happens to be a function call! In which case, we use ~eval~ 336 | which executes code that is in data form; i.e., is quoted. 337 | 338 | #+latex: \room 339 | Macros are essentially functions that return sentences, lists, which may happen to 340 | contain code. 341 | 342 | #+begin_parallel org 343 | #+BEGIN_SRC emacs-lisp 344 | ;; Quotes / sentences / data 345 | '(I am a sentence) 346 | '(+ 1 (+ 1 1)) 347 | 348 | ;; Executing data as code 349 | (eval '(+ 1 (+ 1 1))) ;; ⇒ 3 350 | #+END_SRC 351 | 352 | #+BEGIN_SRC emacs-lisp 353 | (setq name "Jasim") 354 | 355 | ;; Quasi-quotes: Sentences with a 356 | ;; computation, code, in them. 357 | `(Hello ,name and welcome) 358 | `(+ 1 ,(+ 1 1)) ;; ⇒ '(+ 1 2) 359 | #+END_SRC 360 | #+end_parallel 361 | 362 | As the final example shows, Lisp treats data and code interchangeably. 363 | A language that uses the same structure to store data and code is called ‘homoiconic’. 364 | 365 | * Reads 366 | 367 | #+latex: {\color{white}.}\vspace{-1em} 368 | + [[http://sachachua.com/blog/wp-content/uploads/2013/05/How-to-Learn-Emacs-v2-Large.png][How to Learn Emacs: A Hand-drawn One-pager for Beginners / A visual tutorial]] 369 | + [[https://emacs-doctor.com/learn-emacs-lisp-in-15-minutes.html][Learn Emacs Lisp in 15 minutes]] --- https://learnxinyminutes.com/ 370 | + [[https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html#Top][An Introduction to Programming in Emacs Lisp]] @@latex: \hfill ---also @@ [[http://landoflisp.com/][Land of Lisp]] 371 | + [[https://www.gnu.org/software/emacs/manual/html_node/elisp/index.html#Top][GNU Emacs Lisp Reference Manual]] 372 | 373 | * Variables 374 | # (describe-symbol 'make-variable-buffer-local) 375 | 376 | + Global Variables, Create & Update: ~(setq name value)~. 377 | - Generally: ~(setq name₀ value₀ ⋯ nameₖ valueₖ)~. 378 | 379 | Use ~devfar~ for global variables since it 380 | permits a documentation string --but updates must be performed with ~setq~. 381 | E.g., ~(defvar my-x 14 "my cool thing")~. 382 | 383 | :TryItOut: 384 | (defvar my-x 14 "my cool thing") 385 | 386 | my-x ;; ⇒ 14 387 | 388 | (defvar my-x 16 "my cool thing") 389 | 390 | my-x ;; ⇒ 14 still 391 | 392 | (setq my-x 16) 393 | my-x ;; ⇒ now 16 394 | 395 | (describe-symbol 'my-x) 396 | 397 | 398 | :End: 399 | 400 | | ~(setq x y) ≈ (set (quote x) y)~ | 401 | 402 | Variables are assigned with ~set~, 403 | which takes a quoted identifier, so that it's not evaluated, 404 | and a value to associate to that variable. “set quoted”, ~setq~, 405 | avoids the hassle of quoting the name. 406 | More generally, ~(set sym v)~ assigns the /value of/ ~sym~ to have the value ~v~. 407 | 408 | # Of course functions evaluate their arguments, so ~setq~ couldn't possibly be a function. 409 | # It's an uber-function, called a ‘macro’, that doesn't evaluate its arguments before executing. 410 | 411 | + Local Scope: ~(let ((name₀ val₀) … (nameₖ valₖ)) bodyBlock)~. 412 | - ~let*~ permits later bindings to refer to earlier ones. 413 | - The simpler ~let~ indicates to the reader that there are no dependencies between the variables. 414 | - let ≈ parallel; let* ≈ sequential. 415 | - Local functions declared with ~flet~ and ~flet*~; e.g., 416 | ~(flet ((go (x) (+ 2 x))) (go 3))~. 417 | 418 | + Any sequence of symbols is a valid identifier, including ~x, x-y/z, --<<==>>--~ 419 | and even ~∀∃~. Elisp names are case sensitive. 420 | :Try_it_out: 421 | #+BEGIN_SRC emacs-lisp 422 | (setq ∀∃ 23) 423 | (message (format "%s" ∀∃)) 424 | 425 | (setq --<<==>>-- 23) 426 | (message (format "%s" --<<==>>--)) 427 | 428 | (eq '∀∃ '--<<==>>--) ;; false 429 | (eq '∀∃ '∀∃) ;; true 430 | 431 | ;; Elisp names are case sensitive 432 | (eq 'foobar 'fOoBaR) ;; ⇒ false 433 | #+END_SRC 434 | :End: 435 | 436 | + Elisp is dynamically scoped: The caller's stack is accessible by default! 437 | #+BEGIN_SRC emacs-lisp 438 | (defun woah () 439 | "If any caller has a local ‘work’, they're in for a nasty bug 440 | from me! Moreover, they better have ‘a’ defined in scope!" 441 | (setq work (* a 111))) ;; Benefit: Variable-based scoped configuration. 442 | 443 | (defun add-one (x) 444 | "Just adding one to input, innocently calling library method ‘woah’." 445 | (let ((work (+ 1 x)) (a 6)) 446 | (woah) ;; May change ‘work’ or access ‘a’! 447 | work 448 | ) 449 | ) 450 | 451 | ;; (add-one 2) ⇒ 666 452 | #+END_SRC 453 | 454 | :Todo_mention_lexcial_binding: 455 | https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html 456 | :End: 457 | 458 | * spacing COMMENT newpage :ignore: 459 | #+latex: \newpage 460 | * spacing COMMENT newpage :ignore: 461 | #+latex: \newpage 462 | * Lists and List-Like Structures 463 | 464 | + Produce a syntactic, un-evaluated list, we use the single quote: 465 | ~'(1 2 3)~. 466 | 467 | + Construction: ~(cons 'x₀ '(x₁ … xₖ)) → (x₀ x₁ … xₖ)~. 468 | 469 | + Head, or /contents of the address part of the register/: 470 | ~(car '(x₀ x₁ … xₖ)) → x₀~. 471 | 472 | + Tail, or /contents of the decrement part of the register/: 473 | ~(cdr '(x₀ x₁ … xₖ)) → (x₁ … xₖ)~. 474 | 475 | # + Deletion: ~(delete e xs)~ yields ~xs~ with all instance of ~e~ removed. 476 | # - E.g., ~(delete 1 '(2 1 3 4 1)) → '(2 3 4)~. 477 | # 478 | # (describe-symbol 'remove-if-not) ;; “filter” ;-) 479 | 480 | E.g., ~(cons 1 (cons "a" (cons 'nice nil))) ≈ (list 1 "a" 'nice) ≈ '(1 "a" nice)~. 481 | 482 | #+latex: \room 483 | Since variables refer to literals and functions have lambdas as literals, we 484 | can produce forms that take functions as arguments. E.g., the standard ~mapcar~ 485 | may be construed: 486 | #+BEGIN_SRC emacs-lisp 487 | (defun my-mapcar (f xs) 488 | (if (null xs) xs 489 | (cons (funcall f (car xs)) (my-mapcar f (cdr xs))))) 490 | 491 | (my-mapcar (lambda (x) (* 2 x)) '(0 1 2 3 4 5)) ;; ⇒ (0 2 4 6 8 10) 492 | (my-mapcar 'upcase '("a" "b" "cat")) ;; ⇒ ("A" "B" "CAT") 493 | #+END_SRC 494 | 495 | Pairs: ~(x . y) ≈ (cons x y)~. 496 | 497 | An association list, or alist, is a list formed of such pairs. 498 | They're useful for any changeable collection of key-value pairs. 499 | The ~assoc~ function takes a key and an alist and returns the first pair 500 | having that key. In the end, alists are just lists. 501 | 502 | :Try_it_out: 503 | #+BEGIN_SRC emacs-lisp 504 | (setq drinks '( (jasim . coffee) (mary . tea) (jasim . chai) )) 505 | 506 | (assoc 'mary drinks) ;; ⇒ (mary . tea) 507 | (assoc 'jasim drinks) ;; ⇒ (jasim . coffee) 508 | 509 | (push '(mary . cola) drinks) 510 | (assoc 'mary drinks) ;; ⇒ (mary . cola) 511 | #+END_SRC 512 | :End: 513 | 514 | #+latex: \room 515 | (Rose) Trees in lisp are easily formed as lists of lists where each inner 516 | list is of length 2: 517 | The first symbol is the parent node and the second is the list of children. 518 | 519 | #+latex: \room 520 | Lists are formed by chains of cons cells, so getting and setting are very slow; 521 | likewise for alists. If performance is desired, one uses arrays and hash tables, 522 | respectively, instead. In particular, the performance of arrays and hash tables always 523 | requires a constant amount of time whereas the performance of lists and alists grows in 524 | proportion with their lengths. 525 | 526 | However, the size of an array is fixed ---it cannot change and thus grow--- and hash 527 | tables have a lookup cost as well as issues with "hash collisions". Their use is worth 528 | it for large amounts of data, otherwise lists are the way to go. 529 | 530 | #+latex: \room 531 | An [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Arrays.html][array]] is created like a list but using [only square brackets] with getter ~(aref arr index)~. 532 | 533 | A hash table is created with ~(make-hash-table)~ with getter ~(gethash key table)~. 534 | 535 | :Try_it_out: 536 | #+BEGIN_SRC emacs-lisp 537 | (setq x [0 1 2 nice]) 538 | (aref x 3) 539 | (aset x 0 'woah) 540 | 541 | (setq drinks (make-hash-table)) 542 | (setf (gethash 'mary drinks) 'tea) 543 | (setf (gethash 'mary drinks) 'chai) 544 | (gethash 'mary drinks) ;; ⇒ 'chai 545 | #+END_SRC 546 | :End: 547 | 548 | #+latex: \room 549 | What if you look up a key and get ~nil~, is there no value for that key or is the value 550 | ~nil~? ~gethash~ takes a final, optional, argument which is the value to return when the 551 | key is not found; it is ~nil~ by default. 552 | 553 | * Generic Setters 554 | 555 | Since 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~. 556 | Hence, once you have a getter ~G~ you freely obtain a setter ~(setf G ⋯)~. 557 | # G may be arbitrary complex. 558 | 559 | # E.g., ~nth~ is a way to get a value from a list; ~(setf (nth 2 x) 'nice)~ changes the list ~x~ at index ~2~ to have value ~'nice~. 560 | 561 | #+BEGIN_SRC emacs-lisp 562 | ;; Element update 563 | (setq x '(0 1 2 3)) ;; x ⇒ '(0 1 2 3) 564 | (setf (nth 2 x) 'nice) ;; x ⇒ '(0 1 'nice 3) 565 | 566 | ;; Circular list 567 | (setq y '(a b c)) ;; y ⇒ '(a b c) 568 | (setf (cdddr y) y) ;; y ⇒ '(a b c a b . #2) 569 | ;; “#2” means repeat from index 2. 570 | (nth 99 y) ;; ⇒ a 571 | #+END_SRC 572 | 573 | * spacing newpage :ignore: 574 | #+latex: \newpage 575 | * Records 576 | 577 | If we want to keep a list of related properties in a list, then we have to remember 578 | which position keeps track of which item and may write helper functions to keep track 579 | of this. Instead we could use a structure. 580 | :More: 581 | A Lisp "Structure, record, object" represents objects with properties as in OOP. 582 | Make a structure like this: (defstruct X (f1 d1) (f2 d2) ... (fn dn)), this creates a record type named X with slots/properties/fields fi having defaults di or nil if di is absent in which case we simply write fi rather than (fi di), moreover it gives the generic constructor (make-X :f1 val1 :f2 val2 ... :fn valn) where any of the fi is optional and assigned nil by default; projection functions X.fi are also provided automatically. 583 | Printing and reading symmetry works as expected with structures and updates happen with setf as expected. 584 | :End: 585 | 586 | #+BEGIN_SRC elisp 587 | (defstruct X "Record with fields/slots fᵢ having defaults dᵢ" 588 | (f₀ d₀) ⋯ (fₖ dₖ)) 589 | 590 | ;; Automatic constructor is “make-X” with keyword parameters for 591 | ;; initialising any subset of the fields! 592 | ;; Hence (expt 2 (1+ k)) kinds of possible constructor combinations! 593 | (make-X :f₀ val₀ :f₁ val₁ ⋯ :fₖ valₖ) ;; Any, or all, fᵢ may be omitted 594 | 595 | ;; Automatic runtime predicate for the new type. 596 | (X-p (make-X)) ;; ⇒ true 597 | (X-p 'nope) ;; ⇒ nil 598 | 599 | ;; Field accessors “X-fᵢ” take an X record and yield its value. 600 | 601 | ;; Field update: (setf (X-fᵢ x) valᵢ) 602 | 603 | (defstruct book 604 | title (year 0)) 605 | 606 | (setq ladm (make-book :title "Logical Approach to Discrete Math" :year 1993)) 607 | (book-title ladm) ;; ⇒ "Logical Approach to Discrete Math" 608 | (setf (book-title ladm) "LADM") 609 | (book-title ladm) ;; ⇒ "LADM" 610 | #+END_SRC 611 | 612 | Advanced OOP constructs can be found within the CLOS, Common Lisp Object System; 613 | which is also used as a research tool for studying OOP ideas. 614 | 615 | * Block of Code 616 | 617 | Use the ~progn~ function to treat multiple expressions as a single expression. E.g., 618 | #+BEGIN_SRC elisp 619 | (progn 620 | (message "hello") 621 | (setq x (if (< 2 3) 'two-less-than-3)) 622 | (sleep-for 0 500) 623 | (message (format "%s" x)) 624 | (sleep-for 0 500) 625 | 23 ;; Explicit return value 626 | ) 627 | #+END_SRC 628 | This' like curly-braces in C or Java. The difference is that the last expression is considered 629 | the ‘return value’ of the block. 630 | 631 | Herein, a ‘block’ is a number of sequential expressions which needn't be wrapped with a ~progn~ form. 632 | 633 | + Lazy conjunction and disjunction: 634 | - Perform multiple statements but stop when any of them fails, returns ~nil~: ~(and s₀ s₁ … sₖ)~. 635 | * Maybe monad! 636 | - Perform multiple statements until one of them succeeds, returns non-~nil~: ~(or s₀ s₁ … sₖ)~. 637 | 638 | We can coerce a statement ~sᵢ~ to returning non-~nil~ as so: (~progn sᵢ t)~. 639 | Likewise, coerce failure by ~(progn sᵢ nil)~. 640 | 641 | :TryItOut: 642 | #+BEGIN_SRC emacs-lisp 643 | (and 644 | (message "hello") 645 | (progn (sleep-for 0 500) t) 646 | (message "world") 647 | (progn (sleep-for 0 500) t) 648 | nil 649 | (message "bye") 650 | ) 651 | 652 | (or 653 | (message "hello") 654 | (progn (sleep-for 0 500) t) 655 | (message "world") 656 | (progn (sleep-for 0 500) t) 657 | nil 658 | (message "bye") 659 | ) 660 | 661 | (catch 'failure 662 | (cond (message "hello") 663 | (progn (sleep-for 0 500) t) 664 | (message "world") 665 | (progn (sleep-for 0 500) t) 666 | nil 667 | (throw 'failure 99) 668 | (message "bye") 669 | ) 670 | ) 671 | #+END_SRC 672 | 673 | :End: 674 | 675 | + 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~. 676 | - ~(catch 'my-jump bodyBlock)~ where the body may contain ~(throw 'my-jump returnValue)~; 677 | the value of the catch/throw is then ~returnValue~. 678 | - Useful for when the ~bodyBlock~ is, say, a loop. 679 | Then we may have multiple ~catch~'s with different labels according to the nesting of loops. 680 | * Possibly informatively named throw symbol is ~'break~. 681 | - Using name ~'continue~ for the throw symbol and having such a catch/throw as /the body of a loop/ 682 | gives the impression of continue-statements from Java. 683 | - Using name ~'return~ for the throw symbol and having such a catch/throw as the body of a function 684 | definition gives the impression of, possibly multiple, return-statements from Java 685 | --as well as ‘early exits’. 686 | - Simple law: ~(catch 'it s₀ s₁ … sₖ (throw 'it r) sₖ₊₁ ⋯ sₖ₊ₙ) ≈ (progn s₀ s₁ ⋯ sₖ r)~. 687 | * Provided the ~sᵢ~ are simple function application forms. 688 | 689 | + ~and, or~ can be thought of as instance of catch/throw, whence they are control flow 690 | first and Boolean operations second. 691 | #+BEGIN_SRC emacs-lisp 692 | (and s₀ ⋯ sₙ e) ⇒ when all xᵢ are true, do e 693 | (or s₀ ⋯ sₙ e) ⇒ when no xᵢ is true, do e 694 | #+END_SRC 695 | 696 | * Conditionals 697 | 698 | + Booleans: ~nil~, the empty list ~()~, is considered /false/, all else 699 | is /true/. 700 | - Note: ~nil ≈ () ≈ '() ≈ 'nil~. 701 | - (Deep structural) equality: ~(equal x y)~. 702 | - Comparisons: As expected; e.g., ~(<= x y)~ denotes /x ≤ y/. 703 | 704 | + ~(if condition thenExpr optionalElseBlock)~ 705 | - Note: ~(if x y) ≈ (if x y nil)~; \newline better: ~(when c thenBlock) ≈ (if c (progn thenBlock))~. 706 | - Note the else-clause is a ‘block’: Everything after the then-clause is considered to be part of it. 707 | - ~(if xs ⋯)~ means “if xs is nonempty then ⋯” is akin to C style idioms on 708 | linked lists. 709 | 710 | # 711 | #+begin_parallel org 712 | #+BEGIN_SRC emacs-lisp 713 | (cond 714 | (test₀ 715 | actionBlock₀) 716 | (test₁ 717 | actionBlock₁) 718 | … 719 | (t ;; optional 720 | defaultActionBlock)) 721 | #+END_SRC 722 | \columnbreak 723 | #+BEGIN_SRC emacs-lisp 724 | ;; pattern matching on any type 725 | (defun go (x) 726 | (pcase x 727 | ('bob 1972) 728 | (`(,a ,_ ,c) (+ a c)) 729 | (otherwise "Shucks!"))) 730 | 731 | (go 'bob) ;; ⇒ 1972 732 | (go '(1 2 3)) ;; ⇒ 4 733 | (go 'hallo) ;; "Shucks!" 734 | #+END_SRC 735 | #+end_parallel 736 | 737 | Avoid nested if-then-else clauses by using a ~cond~ statement --a (lazy) generalisation 738 | of switch statements: It sequentially evaluates the expressions ~testᵢ~ and 739 | performs only the action of the first true test; yielding ~nil~ when no tests are true. 740 | Or use [[http://www.wilfred.me.uk/blog/2017/03/19/pattern-matching-in-emacs-lisp/][pattern matching]]; which even allows predicates in the case position ---~C-h o~ ;-) 741 | 742 | :Try_it_out: 743 | #+BEGIN_SRC emacs-lisp 744 | (cond 745 | (t (message "first")) 746 | ((/ 2 0) (message "crash")) 747 | ) 748 | #+END_SRC 749 | :End: 750 | 751 | #+latex: \room 752 | Hint: If you write a predicate, think of what else you can return besides ~t~; such as 753 | a witness to why you're returning truth --all non-nil values denote true after all. 754 | E.g., ~(member e xs)~ returns the sublist of ~xs~ that begins with ~e~. 755 | # Return more than just the truth! 756 | 757 | :Try_it_out: 758 | #+BEGIN_SRC emacs-lisp 759 | (member 1 '(2 1 3 5)) 760 | #+END_SRC 761 | :End: 762 | 763 | * spacing COMMENT vfill :ignore: 764 | \vfill 765 | 766 | 767 | * Loops 768 | 769 | Let's sum the first ~100~ numbers in 3 ways. 770 | # 771 | #+begin_parallel org 772 | #+BEGIN_SRC elisp 773 | (let ((n 100) (i 0) (sum 0)) 774 | (while (<= i n) 775 | (incf sum i) (incf i)) 776 | (message (format "sum: %s" sum))) 777 | #+END_SRC 778 | \columnbreak 779 | 780 | | _C_ | _Elisp_ | 781 | | ~x += y~ | ~(incf x y)~ | 782 | | ~x -= y~ | ~(decf x y)~ | 783 | 784 | ~y~ is optional, and is 1 by default. 785 | #+end_parallel 786 | 787 | # dotimes is just a specfic while loop. 788 | # (insert (format "\n\n%s" (macroexpand '(dotimes (x l r) b)))) 789 | 790 | # Two instances of a while loop: 791 | #+BEGIN_SRC elisp 792 | ;; Repeat body n times, where i is current iteration. 793 | (let ((result 0) (n 100)) 794 | (dotimes (i (1+ n) result) (incf result i))) 795 | 796 | ;; A for-each loop: Iterate through the list [0..100]. 797 | (let ((result 0) (mylist (number-sequence 0 100))) 798 | (dolist (e mylist result) (incf result e))) 799 | #+END_SRC 800 | 801 | In both loops, ~result~ is optional and defaults to nil. 802 | It is the return value of the loop expression. 803 | #+latex: \vspace{-1em} 804 | | *Example of Above Constructs* | 805 | #+latex: \vspace{-1em} 806 | #+BEGIN_SRC emacs-lisp 807 | (defun my/cool-function (N D) 808 | "Sum the numbers 0..N that are not divisible by D" 809 | (catch 'return 810 | (when (< N 0) (throw 'return 0)) ;; early exit 811 | (let ((counter 0) (sum 0)) 812 | (catch 'break 813 | (while 'true 814 | (catch 'continue 815 | (incf counter) 816 | (cond ((equal counter N) (throw 'break sum )) 817 | ((zerop (% counter D)) (throw 'continue nil)) 818 | ('otherwise (incf sum counter )) ))))))) 819 | 820 | (my/cool-function 100 3) ;; ⇒ 3267 821 | (my/cool-function 100 5) ;; ⇒ 4000 822 | (my/cool-function -100 7) ;; ⇒ 0 823 | #+END_SRC 824 | 825 | The special [[http://www.gigamonkeys.com/book/loop-for-black-belts.html][loop]] construct provides immensely many options to form 826 | nearly any kind of imperative loop. E.g., Python-style ‘downfrom’ for-loops 827 | and Java do-while loops. I personally prefer functional programming, so wont 828 | look into this much. 829 | 830 | * Exception Handling 831 | 832 | We can attempt a dangerous clause and catch a possible exceptional case 833 | --below we do not do so via ~nil~-- for which we have an associated handler. 834 | # Which handles how to recover from such exceptional circumstances. 835 | #+BEGIN_SRC elisp 836 | (condition-case nil attemptClause (error recoveryBody)) 837 | 838 | (ignore-errors attemptBody) 839 | ≈ (condition-case nil (progn attemptBody) (error nil)) 840 | 841 | (ignore-errors (+ 1 "nope")) ;; ⇒ nil 842 | #+END_SRC 843 | 844 | * Types & Overloading 845 | 846 | Since Lisp is dynamically typed, a variable can have any kind of data, possibly 847 | different kinds if data at different times in running a program. 848 | We can use ~type-of~ to get the type of a given value; suffixing that with ~p~ 849 | gives the associated predicate; \newline e.g., ~function ↦ functionp~. 850 | :More: 851 | The following predicates tell us what kind of data a variable 852 | has: ~numberp, arrayp, characterp,~ 853 | ~consp, functionp, hash-tablep, listp, stringp, and symbolp~. 854 | :End: 855 | 856 | :Details: 857 | Using these we can write functions that behave differently according to the types of 858 | their arguments. However this sort of ad hoc polymorphism can be slow and difficult to 859 | maintain when new types need to be considered. Instead, we could create overloaded 860 | methods using the defmethod command: Lisp decides which one to use by considering the 861 | types, hence the types of each declaration need to differ in at least one argument. 862 | :End: 863 | 864 | :Try_it_out: 865 | #+BEGIN_SRC emacs-lisp 866 | (type-of 3) ;; integer 867 | (type-of "3") ;; string 868 | (type-of 'x) ;; symbol 869 | (type-of '(x . y)) ;; cons 870 | (type-of nil) ;; symbol 871 | (type-of '(1 2 3)) ;; cons 872 | (type-of [1 2 3]) ;; vector 873 | #+END_SRC 874 | :End: 875 | 876 | #+BEGIN_SRC emacs-lisp 877 | ;; Difficult to maintain as more types are added. 878 | (defun sad-add (a b) 879 | (if (and (numberp a) (numberp b)) 880 | (+ a b) 881 | (format "%s + %s" a b)) 882 | ) 883 | 884 | (sad-add 2 3) ;; ⇒ 5 885 | (sad-add 'nice "3") ;; ⇒ "nice + 3" 886 | 887 | ;; Better: Seperation of concerns. 888 | ;; 889 | (cl-defmethod add ((a number) (b number)) (+ a b)) ;; number types 890 | (cl-defmethod add ((a t) (b t)) (format "%s + %s" a b)) ;; catchall types 891 | 892 | (add 2 3) ;; ⇒ 5 893 | (add 'nice "3") ;; ⇒ "nice + 3" 894 | #+END_SRC 895 | 896 | While list specific functions like list-length and mapcar may be more efficient than 897 | generic functions, which require extra type checking, the generic ones are easier to 898 | remember. The following generic functions work on lists, arrays, and strings: 899 | + ~find-if~, gets first value satisfying a predicate. 900 | + ~count~, finds how often an element appears in a sequence 901 | + ~position~, finds the index of a given element. 902 | + ~some~, check if any element satisfies a given predicate 903 | + ~every~, check if every element satisfies the given predicate 904 | + ~reduce~, takes a binary operation and a sequence and mimics a for-loop. 905 | Use keyword ~:initial-value~ to specify the starting value, otherwise use head of 906 | sequence. 907 | + ~sum~, add all numbers; crash for strings. 908 | + ~length, subseq, sort~. 909 | :More: 910 | + ~map~, like ~mapcar~ but works for any sequence with the added ability to transform 911 | sequences to other types: Its first argument could be ~'list~ even if we operate in a 912 | string, so that the list is converted after the operation is mapped. 913 | + ~subseq~, yields subsequence according to given indices. 914 | + ~sort~, takes an ordering relation and sorts according to it. 915 | :End: 916 | 917 | [[https://github.com/magnars/dash.el][dash]] is a modern list library for Emacs that uses Haskell-like names for list operations ;-) 918 | Likewise, [[https://github.com/magnars/s.el][s]] is a useful Emacs string manipulation library. 919 | 920 | In-fact, we can [[https://github.com/knupfer/haskell-emacs][write Emacs extensions using Haskell directly]]. 921 | 922 | * spacing newpage :ignore: 923 | #+latex: \newpage 924 | * Macros 925 | 926 | Macros let us add new syntax, like ~let1~ for single lets: 927 | # 928 | # Need to have a space before using ‘parallel’. 929 | # 930 | #+begin_parallel org 931 | #+BEGIN_SRC emacs-lisp 932 | ;; Noisy parens! 933 | (let ((x "5")) (message x)) 934 | 935 | ;; Better. 936 | (let1 x "5" (message x)) 937 | 938 | ;; How? 939 | (defmacro let1 (var val &rest body) 940 | `(let ((,var ,val)) ,@body)) 941 | 942 | ;; What does it look like? 943 | (macroexpand 944 | '(let1 x "5" (message x))) 945 | ;; ⇒ (let ((x 5)) (message x)) 946 | #+END_SRC 947 | \columnbreak 948 | #+BEGIN_SRC emacs-lisp 949 | ;; No progn; (first x y z) ≈ x 950 | (defmacro first (&rest body) 951 | (car `,@body)) 952 | 953 | ;; Need to use “progn”! 954 | (defmacro not-first (&rest body) 955 | `(progn ,@(cdr `,@body))) 956 | 957 | (macroexpand '(not-first x y z)) 958 | ;; `,@body ⇒ (x y z) 959 | ;; (cdr `,@body) ⇒ (y z) 960 | ;; `(progn ,@(cdr `,@body)) 961 | ;; ⇒ (progn y z) 962 | #+END_SRC 963 | 964 | :Try_it_out: 965 | #+BEGIN_SRC emacs-lisp 966 | (first (insert "x") (insert "y") (message "z")) 967 | 968 | (not-first (insert "x") (insert "y") (message "z")) 969 | #+END_SRC 970 | :End: 971 | 972 | #+end_parallel 973 | 974 | 0. Certain problems are elegantly solved specific language constructs; 975 | e.g., list operations are generally best defined by pattern matching. 976 | # Likewise for any ADT. 977 | 978 | 1. Macros let us /make/ the best way to solve a problem when our language does 979 | not give it to us. 980 | 981 | # --They can also be used to reduce repetitive visual noise. 982 | # Which is achievable by using higher-order operations. 983 | # 984 | # IMHO macros are best for creating new syntax. 985 | 986 | 2. Macro expansion happens before runtime, function execution, and so the 987 | arguments passed to a macro will contain raw source code. 988 | 989 | [[http://www.lispworks.com/documentation/HyperSpec/Body/02_df.htm][Backquotes]] let us use the comma to cause the actual variable /names/ 990 | and /values/ to be used --e.g., ~x~ is a ‘meta-variable’ and its value, ~,x~, 991 | refers to a real variable or value. 992 | 993 | The ~&rest~ marker allows us to have multiple statements at the end of the macro: 994 | The macro expander provides all remaining expressions in the macro as a list, 995 | the contents of which may be inserted in place, not as a list, using the 996 | [[https://www.gnu.org/software/emacs/manual/html_node/elisp/Backquote.html][ ~,@~ splice comma]] --we need to ensure there's a ~progn~. 997 | 998 | Use list elements in-place: 999 | #+latex: \vspace{-1em} 1000 | | ~`(pre ,@(list s₀ ⋯ sₙ) post) ≈ `(pre s₀ ⋯ sₙ post)~ | 1001 | # 1002 | # This works: `(pre ,@'(s0 ⋯ sn) post) 1003 | # ≈ '(pre s0 ⋯ sn post) 1004 | # 1005 | # Woah! 1006 | 1007 | + ~macroexpand~ takes /code/ and expands any macros in it. It's useful in debugging macros. 1008 | The above ‘equations’ can be checked by running ~macroexpand~; \newline e.g., 1009 | ~(when c s₀ ⋯ sₙ) ≈ (if c (progn s₀ ⋯ sₙ) nil)~ holds since: 1010 | 1011 | #+BEGIN_SRC elisp 1012 | (macroexpand '(when c s₀ ⋯ sₙ)) ;; ⇒ (if c (progn s₀ ⋯ sₙ)) 1013 | #+END_SRC 1014 | 1015 | + If ~var~ is an argument to a macro where ~,var~ occurs multiple times, then since 1016 | arguments to macros are raw source code, each occurrence of ~,var~ is an execution of the 1017 | code referenced by ~var~. 1018 | 1019 | #+latex: \room 1020 | Avoid such repeated execution by using a ~let~ to capture the result, call it ~res~, once 1021 | and use the ~res~ in each use site. 1022 | 1023 | #+latex: \room 1024 | Now we've made use of the name ~res~ and our users cannot use that name correctly. 1025 | Avoid such /unintended/ capture by using ~gensym~ to provide us with a globally unique 1026 | name which is bound to a variable, say ~r~, then we bind the result of executing ~var~ 1027 | to the fresh name ~,r~. 1028 | 1029 | #+latex: \room 1030 | Whence: ~`(⋯,var⋯,var⋯)~ 1031 | @@latex:\newline{\color{white}.}\hspace{2em}@@ 1032 | ~⇒ (let ((r (gensym))) `(let ((,r ,var)) ⋯,r⋯,r⋯))~. 1033 | 1034 | #+latex: \room 1035 | Note that the name ~r~ is outside the backquote; it is part of code that is run 1036 | at macro expansion time, not runtime. The value of the final ~let~ is then the backquoted 1037 | matter, which makes /no/ reference to ~r~, but instead makes use of the name it 1038 | refers to, ~,r~. Neato! 1039 | 1040 | #+latex: \room 1041 | Ex., remove repeated execution from ~(defmacro twice (var) `(list ,var ,var))~. 1042 | :Try_it_out: 1043 | #+BEGIN_SRC emacs-lisp 1044 | (defmacro twice (var) 1045 | `(list ,var ,var)) 1046 | 1047 | (macroexpand '(twice x)) 1048 | 1049 | (twice 3) 1050 | (twice (progn (insert "\nwow") 3)) 1051 | 1052 | (defmacro duplicate (var) 1053 | (let1 r (gensym) 1054 | `(let1 ,r ,var 1055 | (list ,r ,r) 1056 | ) 1057 | ) 1058 | ) 1059 | 1060 | (duplicate 3) 1061 | (duplicate (progn (insert "\nwow") 3)) 1062 | #+END_SRC 1063 | :End: 1064 | 1065 | + Test that you don't have accidentally variable capture by passing in an insert 1066 | statement and see how many times insertions are made. 1067 | 1068 | + Macros that /intentionally/ use variable capture as a feature, rather than a bug, 1069 | to provide names available in the macro body are called ‘anaphoric macros’. 1070 | 1071 | #+latex: \room 1072 | E.g., ~(split list no yes)~ provides the names ~head, tail~ in the ~yes~ body 1073 | to refer to the head and tail of the given ~list~, say via a ~let~, but not so in the 1074 | ~no~ argument for when ~list~ is empty. Whence, elegant pattern matching on lists. 1075 | 1076 | #+latex: \room 1077 | Exercise: Define ~split~. 1078 | :Try_it_out: 1079 | #+BEGIN_SRC emacs-lisp 1080 | (defmacro split (list no &rest yes) 1081 | `(if ,list (let ((head (car ,list)) (tail (cdr ,list))) ,@yes) ,no) 1082 | ) 1083 | 1084 | ;; Example use 1085 | 1086 | (defun sum (xs) (split xs 0 (+ head (sum tail)))) 1087 | 1088 | (sum '(1 2 3 4 5)) ;; ⇒ 15 1089 | #+END_SRC 1090 | :End: 1091 | 1092 | * COMMENT Macros :old_notes: 1093 | + Sometimes we don't want eager evaluation; i.e., we do not want to 1094 | recursively evaluate arguments before running a function. 1095 | + /Macros/ let us manipulate a program's abstract syntax tree, usually 1096 | by delaying some computations --easy since Elisp lets us treat code as data. 1097 | 1098 | #+latex: \room 1099 | ~`(e₀ e₁ ⋯ eₖ)~ is known as a /quasi-quote/: It produces syntactic data like ~quote~ 1100 | but allows computations to occur --any expression prefixed with a comma as in ~,e₃~-- 1101 | thereby eagerly evaluating some and delaying evaluation of others. 1102 | 1103 | #+BEGIN_SRC elisp 1104 | (defun my/lazy-or (this that) 1105 | (if this t that)) 1106 | 1107 | (my/lazy-or (print "yup") (print "nope")) ;; evaluates & prints both clauses! 1108 | (my/lazy-or t (/ 2 0)) ;; second clause runs needlessly, causing an error. 1109 | 1110 | ;; Delay argument evaluation using defmacro 1111 | (defmacro my/lazy-or-2 (this that) 1112 | `(if ,this t ,that)) 1113 | 1114 | (my/lazy-or-2 (print "yup") (print "nope")) ;; just "yup" ;-) 1115 | (my/lazy-or-2 t (/ 2 0)) ;; second clause not evaluated 1116 | 1117 | ;; What code is generated by our macro? 1118 | (macroexpand '(my/lazy-or-2 t (/ 2 0))) ;; ⇒ (if t t (/2 0)) 1119 | #+END_SRC 1120 | 1121 | We've added new syntax to Elisp! 1122 | 1123 | #+latex: \room 1124 | The above ‘equations’ can be checked by running ~macroexpand~; \newline e.g., 1125 | ~(when c s₀ ⋯ sₙ) ≈ (if c (progn s₀ ⋯ sₙ) nil)~ holds since 1126 | 1127 | #+BEGIN_SRC elisp 1128 | (macroexpand '(when c s₀ ⋯ sₙ)) ;; ⇒ (if c (progn s₀ ⋯ sₙ)) 1129 | #+END_SRC 1130 | 1131 | Woah! 1132 | 1133 | * spacing COMMENT newpage :ignore: 1134 | #+latex: \newpage 1135 | * COMMENT Hooks 1136 | + We can ‘hook’ methods to run at particular events. 1137 | + Hooks are lists of functions that are, for example, run when a mode is initialised. 1138 | 1139 | # Hooks are lists of functions that are called from Emacs Lisp in order to modify the behaviour of something. 1140 | # For example, different modes have their own hooks so that you can add functions that will run when that mode is initialised. 1141 | 1142 | E.g., 1143 | let's add the ~go~ function to the list of functions when a buffer 1144 | is initialised with org-mode. 1145 | #+BEGIN_SRC elisp 1146 | (describe-symbol 'org-mode-hook) 1147 | 1148 | (defun go () (message-box "It worked!")) 1149 | 1150 | (add-hook 'org-mode-hook 'go) 1151 | ≈ (add-hook 'org-mode-hook '(lambda () (message-box "It worked!"))) 1152 | ≈ (add-to-list 'org-mode-hook 'go) 1153 | 1154 | ;; Now execute: (revert-buffer) to observe “go” being executed. 1155 | ;; Later remove this silly function from the list: 1156 | (remove-hook 'org-mode-hook 'go) 1157 | #+END_SRC 1158 | 1159 | + The ~'after-init-hook~ event will run functions after the rest of the init-file has finished loading. 1160 | 1161 | * spacing vfill :ignore: 1162 | \vfill 1163 | 1164 | * ~read~ and ~print~ 1165 | 1166 | ‘Reading’ means parsing an expression in textual form and producing a lisp object. 1167 | E.g., this is a way to load a lisp file. ‘Printing’ a lisp object mean producing 1168 | a textual representation. These operations, in lisp, are mostly inverse. 1169 | 1170 | #+latex: \room 1171 | The ~read-from-string~ command works just like the ~read~ command, but 1172 | lets us read a lisp object from a string instead of directly from the console. 1173 | 1174 | #+BEGIN_SRC emacs-lisp 1175 | (defun sum-two () 1176 | (let (fst snd) 1177 | (setq fst (read)) 1178 | (setq snd (read)) 1179 | (+ (eval fst) (eval snd)) 1180 | ) 1181 | ) 1182 | 1183 | ;; Run (sum-two) with inputs (+ 1 2) and (* 3 4) ;-) 1184 | #+END_SRC 1185 | 1186 | Lisp makes writing a REPL astonishingly easy: “Loop as follows: 1187 | Print the result of evaluating what is read at the prompt.” 1188 | #+BEGIN_SRC emacs-lisp 1189 | (loop (print (eval (read)))) ;; Beautiful ♥‿♥ 1190 | #+END_SRC 1191 | 1192 | + ~loop~ merely loops forever. 1193 | 1194 | The ~print~ and ~read~ commands work on all kinds of data, such as lists of data 1195 | structures. Hence, we must use quotes if we want to read a string rather than a 1196 | symbol, for example. 1197 | 1198 | #+latex: \room 1199 | A major problem with this REPL is that ~eval~ executes any, potentially malicious, 1200 | Lisp command entered by the user. Ideally one checks the read lisp object is 1201 | safe ---say, it is one of some allowable commands--- and only then evaluates it. 1202 | :A_safer_repl: 1203 | #+BEGIN_SRC emacs-lisp 1204 | (defun f () (message-box "f was called")) 1205 | (defun g () (message-box "g was called")) 1206 | (defun h () (message-box "h was called")) 1207 | (setq safe-commands '(f g h)) 1208 | 1209 | ;; This reply can only execute: (f), (g), (h), quit 1210 | (catch 'quit 1211 | (loop 1212 | (let ((sexp (read))) 1213 | (when (equal sexp 'quit) (throw 'quit "byebye")) 1214 | (if (member (car sexp) safe-commands) 1215 | (eval sexp) 1216 | '(I do not know that command))))) 1217 | #+END_SRC 1218 | :End: 1219 | 1220 | * TODO COMMENT Format --land of lisp 1221 | 1222 | Format :: 223 discuss a and s, ~& for printing a new line if need be whence no ugly empty lines, 228 for ~t, 231 for printings lists. Format is a dsl, there's so much! 1223 | 1224 | * COMMENT Making README.md 1225 | 1226 | C-c C-c: Evaluate src block. 1227 | 1228 | #+NAME: make-readme 1229 | #+BEGIN_SRC elisp :results none 1230 | (with-temp-buffer 1231 | (insert 1232 | "#+EXPORT_FILE_NAME: README.md 1233 | ,#+HTML:

ElispCheatSheet

1234 | ,#+OPTIONS: toc:nil d:nil 1235 | # Toc is displayed below at a strategic position. 1236 | 1237 | Quick reference to the core language of Emacs ---Editor MACroS. 1238 | 1239 | ◈ [[https://alhassy.github.io/ElispCheatSheet/][Website]] ◈ 1240 | 1241 | ( It's mostly Common Lisp in Elisp syntax, for now; based on reading Land of Lisp. ) 1242 | # ( Much Emacs Lisp was utilised in making my [[blog][https://alhassy.github.io]] ) 1243 | 1244 | ,*The listing sheet, as PDF, can be found 1245 | [here]({{{URL}}}/blob/master/CheatSheet.pdf)*, 1246 | while below is an unruly html rendition. 1247 | 1248 | This reference sheet is built around 1249 | [[https://github.com/alhassy/CheatSheet][an Org-mode CheatSheet system]]. 1250 | 1251 | ,#+TOC: headlines 2 1252 | ,#+INCLUDE: CheatSheet.org 1253 | ") 1254 | ;; (set-visited-file-name "ReadIt2.md") 1255 | (org-mode) 1256 | (org-md-export-to-markdown) 1257 | ) 1258 | #+END_SRC 1259 | 1260 | * COMMENT footer 1261 | 1262 | # Local Variables: 1263 | # eval: (progn (org-babel-goto-named-src-block "make-readme") (org-babel-execute-src-block) (outline-hide-sublevels 1)) 1264 | # End: 1265 | -------------------------------------------------------------------------------- /CheatSheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alhassy/ElispCheatSheet/ee1ca6ac5809b89b3910915ec043470dd09c0afb/CheatSheet.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

ElispCheatSheet

2 | 3 | Quick reference to the core language of Emacs —Editor MACroS. 4 | 5 | ◈ [Website](https://alhassy.github.io/ElispCheatSheet/) ◈ 6 | 7 | ( It's mostly Common Lisp in Elisp syntax, for now; based on reading Land of Lisp. ) 8 | 9 | **The listing sheet, as PDF, can be found 10 | [here]()**, 11 | while below is an unruly html rendition. 12 | 13 | This reference sheet is built around 14 | [an Org-mode CheatSheet system](https://github.com/alhassy/CheatSheet). 15 | 16 | 17 | # Table of Contents 18 | 19 | 1. [Functions](#orgcae400a) 20 | 2. [Quotes, Quasi-Quotes, and Unquotes](#orge624d54) 21 | 3. [Reads](#orgdb68da1) 22 | 4. [Variables](#org943c427) 23 | 5. [Lists and List-Like Structures](#orgbc87d9e) 24 | 6. [Generic Setters](#org8ccfbc7) 25 | 7. [Records](#org71dcb45) 26 | 8. [Block of Code](#org9c71fdf) 27 | 9. [Conditionals](#orgaa669ec) 28 | 10. [Loops](#org45458fb) 29 | 11. [Exception Handling](#orgeb7a6f7) 30 | 12. [Types & Overloading](#org825332f) 31 | 13. [Macros](#orgc487ae3) 32 | 14. [`read` and `print`](#org7ece87e) 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | *Everything is a list!* 47 | 48 | - To find out more about `name` execute `(describe-symbol 'name)`! 49 | - After the closing parens invoke `C-x C-e` to evaluate. 50 | - To find out more about a key press, execute `C-h k` then the key press. 51 | - To find out more about the current mode you're in, execute `C-h m` or 52 | `describe-mode`. Essentially a comprehensive yet terse reference is provided. 53 | 54 | 55 | 56 | 57 | # Functions 58 | 59 | - Function invocation: `(f x₀ x₁ … xₙ)`. E.g., `(+ 3 4)` or `(message "hello")`. 60 | - After the closing parens invoke `C-x C-e` to execute them. 61 | - *Warning!* Arguments are evaluated **before** the function is executed. 62 | - Only prefix invocations means we can use `-,+,*` in *names* 63 | since `(f+*- a b)` is parsed as applying function `f+*-` to arguments `a, b`. 64 | 65 | E.g., `(1+ 42) → 43` using function *named* `1+` —the ‘successor function’. 66 | 67 | - Function definition: 68 | 69 | ;; “de”fine “fun”ctions 70 | (defun my-fun (arg₀ arg₁ … argₖ) ;; header, signature 71 | "This functions performs task …" ;; documentation, optional 72 | …sequence of instructions to perform… ) ;; body 73 | 74 | - The return value of the function is the result of the last expression executed. 75 | - The documentation string may indicate the return type, among other things. 76 | 77 | - Anonymous functions: `(lambda (arg₀ … argₖ) bodyHere)`. 78 | 79 |
80 | ;; make then way later invoke 81 | (setq my-f (lambda (x y) (+ x y))) 82 | (funcall my-f 1 2) ;; ⇒ 3 83 | ;; (my-f 1 2) ;; invalid! 84 | (funcall my-f 1 2) ;; ⇒ 3 85 | 86 | \columnbreak 87 | 88 | ;; make and immediately invoke 89 | (funcall (lambda (x y) (+ x y)) 1 2) 90 | 91 | ;; works, but is deprecated 92 | ((lambda (x y) (+ x y)) 1 2) 93 | 94 |
95 | 96 | Functions are first-class values *but* variables and functions have **separate namespaces** 97 | —“Elisp is a Lisp-2 Language”. 98 | The function represented by the name *g* is obtained 99 | by the call `(function g)`, which is also denoted `#'g`. 100 | The sharp quote behaves like the usual quote but causes its argument to be compiled. 101 | `lambda` is a macro that calls `function` and so there is rarely any need to quote lambdas. 102 | If `h` is a variable referring to a function, then `(funcall h x₀ … xₙ)` 103 | calls that function on arguments `xᵢ`. 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 |
`(apply 'g x₀…xₖ '(xₖ…xₙ)) ≈ (funcall #'g x₀…xₙ) ≈ (g x₀…xₙ)`
117 | 118 | ;; Recursion with the ‘tri’angle numbers: tri n = Σⁿᵢ₌₀ i. 119 | (defun tri (f n) (if (<= n 0) 0 (+ (funcall f n) (tri f (- n 1))))) 120 | (tri #'identity 100) ;; ⇒ 5050 121 | (tri (lambda (x) (/ x 2)) 100) ;; ⇒ 2500 122 | 123 | ;; Run “C-h o tri” to see TWO items! Location determines dispatch. 124 | (setq tri 100) (tri #'identity tri) ;; ⇒ 5050 125 | (setq tri (lambda (x) x)) (tri tri 100) ;; ⇒ 5050 126 | 127 | - **→:** Use `funcall` or `apply` to call functions bound to variables. 128 | - **→:** Refer to functions outside of function calls by using a sharp quote, `#'`. 129 | 130 | We may have positional `optional` arguments, or optional but named arguments 131 | —for which position does not matter. 132 | Un-supplied optional arguments are bound to `nil`. 133 | 134 |
135 | (cl-defun f (a &optional b (c 5)) 136 | (format "%s %s %s" a b c)) 137 | 138 | (f 'a) ;; ⇒ "a nil 5" 139 | (f 'a 'b) ;; ⇒ "a b 5" 140 | (f 'a 'b 'c) ;; ⇒ "a b c" 141 | 142 | (cl-defun g (a &key (b 'nice) c) 143 | (format "%s %s %s" a b c)) 144 | 145 | (g 1 :c 3 :b 2) ;; ⇒ "1 2 3" 146 | (g 1 :c 3) ;; ⇒ "1 nice 3" 147 | 148 |
149 | 150 | Keywords begin with a colon, `:k` is a constant whose value is `:k`. 151 | 152 | 153 | 154 | 155 | # Quotes, Quasi-Quotes, and Unquotes 156 | 157 | Quotes: `'x` refers to the *name* rather than the *value* of `x`. 158 | 159 | - This is superficially similar to pointers: 160 | Given `int *x = …`, `x` is the name (address) 161 | whereas `*x` is the value. 162 | - The quote simply forbids evaluation; it means *take it literally as you see it* 163 | rather than looking up the definition and evaluating. 164 | - Note: `'x ≈ (quote x)`. 165 | 166 | Akin to English, quoting a word refers to the word and not what it denotes. 167 | 168 | This lets us treat *code* as *data*! E.g., `'(+ 1 2)` evaluates to `(+ 1 2)`, a function call, 169 | not the value `3`! Another example, `*` is code but `'*` 170 | is data, and so `(funcall '* 2 4)` yields 8. 171 | 172 | *Elisp expressions are either atoms or function application –nothing else!* 173 | 174 | ‘Atoms’ are the simplest objects in Elisp: They evaluate to themselves; \newline 175 | e.g., `5, "a", 2.78, 'hello, [1 "two" three]`. 176 | 177 | An English sentence is a list of words; if we want to make a sentence where some of 178 | the words are parameters, then we use a quasi-quote –it's like a quote, but allows 179 | us to evaluate data if we prefix it with a comma. It's usually the case that the 180 | quasi-quoted sentence happens to be a function call! In which case, we use `eval` 181 | which executes code that is in data form; i.e., is quoted. 182 | 183 | Macros are essentially functions that return sentences, lists, which may happen to 184 | contain code. 185 | 186 |
187 | ;; Quotes / sentences / data 188 | '(I am a sentence) 189 | '(+ 1 (+ 1 1)) 190 | 191 | ;; Executing data as code 192 | (eval '(+ 1 (+ 1 1))) ;; ⇒ 3 193 | 194 | (setq name "Jasim") 195 | 196 | ;; Quasi-quotes: Sentences with a 197 | ;; computation, code, in them. 198 | `(Hello ,name and welcome) 199 | `(+ 1 ,(+ 1 1)) ;; ⇒ '(+ 1 2) 200 | 201 |
202 | 203 | As the final example shows, Lisp treats data and code interchangeably. 204 | A language that uses the same structure to store data and code is called ‘homoiconic’. 205 | 206 | 207 | 208 | 209 | # Reads 210 | 211 | - [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) 212 | - [Learn Emacs Lisp in 15 minutes](https://emacs-doctor.com/learn-emacs-lisp-in-15-minutes.html) — 213 | - [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/) 214 | - [GNU Emacs Lisp Reference Manual](https://www.gnu.org/software/emacs/manual/html_node/elisp/index.html#Top) 215 | 216 | 217 | 218 | 219 | # Variables 220 | 221 | - Global Variables, Create & Update: `(setq name value)`. 222 | 223 | - Generally: `(setq name₀ value₀ ⋯ nameₖ valueₖ)`. 224 | 225 | Use `devfar` for global variables since it 226 | permits a documentation string –but updates must be performed with `setq`. 227 | E.g., `(defvar my-x 14 "my cool thing")`. 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 |
`(setq x y) ≈ (set (quote x) y)`
241 | 242 | Variables are assigned with `set`, 243 | which takes a quoted identifier, so that it's not evaluated, 244 | and a value to associate to that variable. “set quoted”, `setq`, 245 | avoids the hassle of quoting the name. 246 | More generally, `(set sym v)` assigns the *value of* `sym` to have the value `v`. 247 | 248 | - Local Scope: `(let ((name₀ val₀) … (nameₖ valₖ)) bodyBlock)`. 249 | - `let*` permits later bindings to refer to earlier ones. 250 | - The simpler `let` indicates to the reader that there are no dependencies between the variables. 251 | - let ≈ parallel; let\* ≈ sequential. 252 | - Local functions declared with `flet` and `flet*`; e.g., 253 | `(flet ((go (x) (+ 2 x))) (go 3))`. 254 | 255 | - Any sequence of symbols is a valid identifier, including `x, x-y/z, --<<==>>--` 256 | and even `∀∃`. Elisp names are case sensitive. 257 | 258 | - Elisp is dynamically scoped: The caller's stack is accessible by default! 259 | 260 | (defun woah () 261 | "If any caller has a local ‘work’, they're in for a nasty bug 262 | from me! Moreover, they better have ‘a’ defined in scope!" 263 | (setq work (* a 111))) ;; Benefit: Variable-based scoped configuration. 264 | 265 | (defun add-one (x) 266 | "Just adding one to input, innocently calling library method ‘woah’." 267 | (let ((work (+ 1 x)) (a 6)) 268 | (woah) ;; May change ‘work’ or access ‘a’! 269 | work 270 | ) 271 | ) 272 | 273 | ;; (add-one 2) ⇒ 666 274 | 275 | 276 | 277 | 278 | # Lists and List-Like Structures 279 | 280 | - Produce a syntactic, un-evaluated list, we use the single quote: 281 | `'(1 2 3)`. 282 | 283 | - Construction: `(cons 'x₀ '(x₁ … xₖ)) → (x₀ x₁ … xₖ)`. 284 | 285 | - Head, or *contents of the address part of the register*: 286 | `(car '(x₀ x₁ … xₖ)) → x₀`. 287 | 288 | - Tail, or *contents of the decrement part of the register*: 289 | `(cdr '(x₀ x₁ … xₖ)) → (x₁ … xₖ)`. 290 | 291 | E.g., `(cons 1 (cons "a" (cons 'nice nil))) ≈ (list 1 "a" 'nice) ≈ '(1 "a" nice)`. 292 | 293 | Since variables refer to literals and functions have lambdas as literals, we 294 | can produce forms that take functions as arguments. E.g., the standard `mapcar` 295 | may be construed: 296 | 297 | (defun my-mapcar (f xs) 298 | (if (null xs) xs 299 | (cons (funcall f (car xs)) (my-mapcar f (cdr xs))))) 300 | 301 | (my-mapcar (lambda (x) (* 2 x)) '(0 1 2 3 4 5)) ;; ⇒ (0 2 4 6 8 10) 302 | (my-mapcar 'upcase '("a" "b" "cat")) ;; ⇒ ("A" "B" "CAT") 303 | 304 | Pairs: `(x . y) ≈ (cons x y)`. 305 | 306 | An association list, or alist, is a list formed of such pairs. 307 | They're useful for any changeable collection of key-value pairs. 308 | The `assoc` function takes a key and an alist and returns the first pair 309 | having that key. In the end, alists are just lists. 310 | 311 | (Rose) Trees in lisp are easily formed as lists of lists where each inner 312 | list is of length 2: 313 | The first symbol is the parent node and the second is the list of children. 314 | 315 | Lists are formed by chains of cons cells, so getting and setting are very slow; 316 | likewise for alists. If performance is desired, one uses arrays and hash tables, 317 | respectively, instead. In particular, the performance of arrays and hash tables always 318 | requires a constant amount of time whereas the performance of lists and alists grows in 319 | proportion with their lengths. 320 | 321 | However, the size of an array is fixed —it cannot change and thus grow— and hash 322 | tables have a lookup cost as well as issues with "hash collisions". Their use is worth 323 | it for large amounts of data, otherwise lists are the way to go. 324 | 325 | An [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)`. 326 | 327 | A hash table is created with `(make-hash-table)` with getter `(gethash key table)`. 328 | 329 | What if you look up a key and get `nil`, is there no value for that key or is the value 330 | `nil`? `gethash` takes a final, optional, argument which is the value to return when the 331 | key is not found; it is `nil` by default. 332 | 333 | 334 | 335 | 336 | # Generic Setters 337 | 338 | Since 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`. 339 | Hence, once you have a getter `G` you freely obtain a setter `(setf G ⋯)`. 340 | 341 | ;; Element update 342 | (setq x '(0 1 2 3)) ;; x ⇒ '(0 1 2 3) 343 | (setf (nth 2 x) 'nice) ;; x ⇒ '(0 1 'nice 3) 344 | 345 | ;; Circular list 346 | (setq y '(a b c)) ;; y ⇒ '(a b c) 347 | (setf (cdddr y) y) ;; y ⇒ '(a b c a b . #2) 348 | ;; “#2” means repeat from index 2. 349 | (nth 99 y) ;; ⇒ a 350 | 351 | 352 | 353 | 354 | 355 | # Records 356 | 357 | If we want to keep a list of related properties in a list, then we have to remember 358 | which position keeps track of which item and may write helper functions to keep track 359 | of this. Instead we could use a structure. 360 | 361 | (defstruct X "Record with fields/slots fᵢ having defaults dᵢ" 362 | (f₀ d₀) ⋯ (fₖ dₖ)) 363 | 364 | ;; Automatic constructor is “make-X” with keyword parameters for 365 | ;; initialising any subset of the fields! 366 | ;; Hence (expt 2 (1+ k)) kinds of possible constructor combinations! 367 | (make-X :f₀ val₀ :f₁ val₁ ⋯ :fₖ valₖ) ;; Any, or all, fᵢ may be omitted 368 | 369 | ;; Automatic runtime predicate for the new type. 370 | (X-p (make-X)) ;; ⇒ true 371 | (X-p 'nope) ;; ⇒ nil 372 | 373 | ;; Field accessors “X-fᵢ” take an X record and yield its value. 374 | 375 | ;; Field update: (setf (X-fᵢ x) valᵢ) 376 | 377 | (defstruct book 378 | title (year 0)) 379 | 380 | (setq ladm (make-book :title "Logical Approach to Discrete Math" :year 1993)) 381 | (book-title ladm) ;; ⇒ "Logical Approach to Discrete Math" 382 | (setf (book-title ladm) "LADM") 383 | (book-title ladm) ;; ⇒ "LADM" 384 | 385 | Advanced OOP constructs can be found within the CLOS, Common Lisp Object System; 386 | which is also used as a research tool for studying OOP ideas. 387 | 388 | 389 | 390 | 391 | # Block of Code 392 | 393 | Use the `progn` function to treat multiple expressions as a single expression. E.g., 394 | 395 | (progn 396 | (message "hello") 397 | (setq x (if (< 2 3) 'two-less-than-3)) 398 | (sleep-for 0 500) 399 | (message (format "%s" x)) 400 | (sleep-for 0 500) 401 | 23 ;; Explicit return value 402 | ) 403 | 404 | This' like curly-braces in C or Java. The difference is that the last expression is considered 405 | the ‘return value’ of the block. 406 | 407 | Herein, a ‘block’ is a number of sequential expressions which needn't be wrapped with a `progn` form. 408 | 409 | - Lazy conjunction and disjunction: 410 | 411 | - Perform multiple statements but stop when any of them fails, returns `nil`: `(and s₀ s₁ … sₖ)`. 412 | - Maybe monad! 413 | - Perform multiple statements until one of them succeeds, returns non-`nil`: `(or s₀ s₁ … sₖ)`. 414 | 415 | We can coerce a statement `sᵢ` to returning non-`nil` as so: (`progn sᵢ t)`. 416 | Likewise, coerce failure by `(progn sᵢ nil)`. 417 | 418 | - 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`. 419 | 420 | - `(catch 'my-jump bodyBlock)` where the body may contain `(throw 'my-jump returnValue)`; 421 | 422 | the value of the catch/throw is then `returnValue`. 423 | 424 | - Useful for when the `bodyBlock` is, say, a loop. 425 | Then we may have multiple `catch`'s with different labels according to the nesting of loops. 426 | - Possibly informatively named throw symbol is `'break`. 427 | - Using name `'continue` for the throw symbol and having such a catch/throw as *the body of a loop* 428 | gives the impression of continue-statements from Java. 429 | - Using name `'return` for the throw symbol and having such a catch/throw as the body of a function 430 | definition gives the impression of, possibly multiple, return-statements from Java 431 | –as well as ‘early exits’. 432 | - Simple law: `(catch 'it s₀ s₁ … sₖ (throw 'it r) sₖ₊₁ ⋯ sₖ₊ₙ) ≈ (progn s₀ s₁ ⋯ sₖ r)`. 433 | - Provided the `sᵢ` are simple function application forms. 434 | 435 | - `and, or` can be thought of as instance of catch/throw, whence they are control flow 436 | first and Boolean operations second. 437 | 438 | (and s₀ ⋯ sₙ e) ⇒ when all xᵢ are true, do e 439 | (or s₀ ⋯ sₙ e) ⇒ when no xᵢ is true, do e 440 | 441 | 442 | 443 | 444 | # Conditionals 445 | 446 | - Booleans: `nil`, the empty list `()`, is considered *false*, all else 447 | is *true*. 448 | - Note: `nil ≈ () ≈ '() ≈ 'nil`. 449 | - (Deep structural) equality: `(equal x y)`. 450 | - Comparisons: As expected; e.g., `(<= x y)` denotes *x ≤ y*. 451 | 452 | - `(if condition thenExpr optionalElseBlock)` 453 | - Note: `(if x y) ≈ (if x y nil)`; \newline better: `(when c thenBlock) ≈ (if c (progn thenBlock))`. 454 | - Note the else-clause is a ‘block’: Everything after the then-clause is considered to be part of it. 455 | - `(if xs ⋯)` means “if xs is nonempty then ⋯” is akin to C style idioms on 456 | linked lists. 457 | 458 |
459 | (cond 460 | (test₀ 461 | actionBlock₀) 462 | (test₁ 463 | actionBlock₁) 464 | … 465 | (t ;; optional 466 | defaultActionBlock)) 467 | 468 | \columnbreak 469 | 470 | ;; pattern matching on any type 471 | (defun go (x) 472 | (pcase x 473 | ('bob 1972) 474 | (`(,a ,_ ,c) (+ a c)) 475 | (otherwise "Shucks!"))) 476 | 477 | (go 'bob) ;; ⇒ 1972 478 | (go '(1 2 3)) ;; ⇒ 4 479 | (go 'hallo) ;; "Shucks!" 480 | 481 |
482 | 483 | Avoid nested if-then-else clauses by using a `cond` statement –a (lazy) generalisation 484 | of switch statements: It sequentially evaluates the expressions `testᵢ` and 485 | performs only the action of the first true test; yielding `nil` when no tests are true. 486 | Or 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` ;-) 487 | 488 | Hint: If you write a predicate, think of what else you can return besides `t`; such as 489 | a witness to why you're returning truth –all non-nil values denote true after all. 490 | E.g., `(member e xs)` returns the sublist of `xs` that begins with `e`. 491 | 492 | 493 | 494 | 495 | # Loops 496 | 497 | Let's sum the first `100` numbers in 3 ways. 498 | 499 |
500 | (let ((n 100) (i 0) (sum 0)) 501 | (while (<= i n) 502 | (incf sum i) (incf i)) 503 | (message (format "sum: %s" sum))) 504 | 505 | \columnbreak 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 |
CElisp
`x += y``(incf x y)`
`x -= y``(decf x y)`
534 | 535 | `y` is optional, and is 1 by default. 536 | 537 |
538 | 539 | ;; Repeat body n times, where i is current iteration. 540 | (let ((result 0) (n 100)) 541 | (dotimes (i (1+ n) result) (incf result i))) 542 | 543 | ;; A for-each loop: Iterate through the list [0..100]. 544 | (let ((result 0) (mylist (number-sequence 0 100))) 545 | (dolist (e mylist result) (incf result e))) 546 | 547 | In both loops, `result` is optional and defaults to nil. 548 | It is the return value of the loop expression. 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 |
**Example of Above Constructs**
562 | 563 | (defun my/cool-function (N D) 564 | "Sum the numbers 0..N that are not divisible by D" 565 | (catch 'return 566 | (when (< N 0) (throw 'return 0)) ;; early exit 567 | (let ((counter 0) (sum 0)) 568 | (catch 'break 569 | (while 'true 570 | (catch 'continue 571 | (incf counter) 572 | (cond ((equal counter N) (throw 'break sum )) 573 | ((zerop (% counter D)) (throw 'continue nil)) 574 | ('otherwise (incf sum counter )) ))))))) 575 | 576 | (my/cool-function 100 3) ;; ⇒ 3267 577 | (my/cool-function 100 5) ;; ⇒ 4000 578 | (my/cool-function -100 7) ;; ⇒ 0 579 | 580 | The special [loop](http://www.gigamonkeys.com/book/loop-for-black-belts.html) construct provides immensely many options to form 581 | nearly any kind of imperative loop. E.g., Python-style ‘downfrom’ for-loops 582 | and Java do-while loops. I personally prefer functional programming, so wont 583 | look into this much. 584 | 585 | 586 | 587 | 588 | # Exception Handling 589 | 590 | We can attempt a dangerous clause and catch a possible exceptional case 591 | –below we do not do so via `nil`– for which we have an associated handler. 592 | 593 | (condition-case nil attemptClause (error recoveryBody)) 594 | 595 | (ignore-errors attemptBody) 596 | ≈ (condition-case nil (progn attemptBody) (error nil)) 597 | 598 | (ignore-errors (+ 1 "nope")) ;; ⇒ nil 599 | 600 | 601 | 602 | 603 | # Types & Overloading 604 | 605 | Since Lisp is dynamically typed, a variable can have any kind of data, possibly 606 | different kinds if data at different times in running a program. 607 | We can use `type-of` to get the type of a given value; suffixing that with `p` 608 | gives the associated predicate; \newline e.g., `function ↦ functionp`. 609 | 610 | ;; Difficult to maintain as more types are added. 611 | (defun sad-add (a b) 612 | (if (and (numberp a) (numberp b)) 613 | (+ a b) 614 | (format "%s + %s" a b)) 615 | ) 616 | 617 | (sad-add 2 3) ;; ⇒ 5 618 | (sad-add 'nice "3") ;; ⇒ "nice + 3" 619 | 620 | ;; Better: Seperation of concerns. 621 | ;; 622 | (cl-defmethod add ((a number) (b number)) (+ a b)) ;; number types 623 | (cl-defmethod add ((a t) (b t)) (format "%s + %s" a b)) ;; catchall types 624 | 625 | (add 2 3) ;; ⇒ 5 626 | (add 'nice "3") ;; ⇒ "nice + 3" 627 | 628 | While list specific functions like list-length and mapcar may be more efficient than 629 | generic functions, which require extra type checking, the generic ones are easier to 630 | remember. The following generic functions work on lists, arrays, and strings: 631 | 632 | - `find-if`, gets first value satisfying a predicate. 633 | - `count`, finds how often an element appears in a sequence 634 | - `position`, finds the index of a given element. 635 | - `some`, check if any element satisfies a given predicate 636 | - `every`, check if every element satisfies the given predicate 637 | - `reduce`, takes a binary operation and a sequence and mimics a for-loop. 638 | Use keyword `:initial-value` to specify the starting value, otherwise use head of 639 | sequence. 640 | - `sum`, add all numbers; crash for strings. 641 | - `length, subseq, sort`. 642 | 643 | [dash](https://github.com/magnars/dash.el) is a modern list library for Emacs that uses Haskell-like names for list operations ;-) 644 | Likewise, [s](https://github.com/magnars/s.el) is a useful Emacs string manipulation library. 645 | 646 | In-fact, we can [write Emacs extensions using Haskell directly](https://github.com/knupfer/haskell-emacs). 647 | 648 | 649 | 650 | 651 | 652 | # Macros 653 | 654 | Macros let us add new syntax, like `let1` for single lets: 655 | 656 |
657 | ;; Noisy parens! 658 | (let ((x "5")) (message x)) 659 | 660 | ;; Better. 661 | (let1 x "5" (message x)) 662 | 663 | ;; How? 664 | (defmacro let1 (var val &rest body) 665 | `(let ((,var ,val)) ,@body)) 666 | 667 | ;; What does it look like? 668 | (macroexpand 669 | '(let1 x "5" (message x))) 670 | ;; ⇒ (let ((x 5)) (message x)) 671 | 672 | \columnbreak 673 | 674 | ;; No progn; (first x y z) ≈ x 675 | (defmacro first (&rest body) 676 | (car `,@body)) 677 | 678 | ;; Need to use “progn”! 679 | (defmacro not-first (&rest body) 680 | `(progn ,@(cdr `,@body))) 681 | 682 | (macroexpand '(not-first x y z)) 683 | ;; `,@body ⇒ (x y z) 684 | ;; (cdr `,@body) ⇒ (y z) 685 | ;; `(progn ,@(cdr `,@body)) 686 | ;; ⇒ (progn y z) 687 | 688 |
689 | 690 | 1. Certain problems are elegantly solved specific language constructs; 691 | e.g., list operations are generally best defined by pattern matching. 692 | 693 | 2. Macros let us *make* the best way to solve a problem when our language does 694 | not give it to us. 695 | 696 | 3. Macro expansion happens before runtime, function execution, and so the 697 | arguments passed to a macro will contain raw source code. 698 | 699 | [Backquotes](http://www.lispworks.com/documentation/HyperSpec/Body/02_df.htm) let us use the comma to cause the actual variable *names* 700 | and *values* to be used –e.g., `x` is a ‘meta-variable’ and its value, `,x`, 701 | refers to a real variable or value. 702 | 703 | The `&rest` marker allows us to have multiple statements at the end of the macro: 704 | The macro expander provides all remaining expressions in the macro as a list, 705 | the contents of which may be inserted in place, not as a list, using the 706 | [ `,@` splice comma](https://www.gnu.org/software/emacs/manual/html_node/elisp/Backquote.html) –we need to ensure there's a `progn`. 707 | 708 | Use list elements in-place: 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 |
`` `(pre ,@(list s₀ ⋯ sₙ) post) ≈ `(pre s₀ ⋯ sₙ post) ``
722 | 723 | - `macroexpand` takes *code* and expands any macros in it. It's useful in debugging macros. 724 | The above ‘equations’ can be checked by running `macroexpand`; \newline e.g., 725 | `(when c s₀ ⋯ sₙ) ≈ (if c (progn s₀ ⋯ sₙ) nil)` holds since: 726 | 727 | (macroexpand '(when c s₀ ⋯ sₙ)) ;; ⇒ (if c (progn s₀ ⋯ sₙ)) 728 | 729 | - If `var` is an argument to a macro where `,var` occurs multiple times, then since 730 | arguments to macros are raw source code, each occurrence of `,var` is an execution of the 731 | code referenced by `var`. 732 | 733 | Avoid such repeated execution by using a `let` to capture the result, call it `res`, once 734 | and use the `res` in each use site. 735 | 736 | Now we've made use of the name `res` and our users cannot use that name correctly. 737 | Avoid such *unintended* capture by using `gensym` to provide us with a globally unique 738 | name which is bound to a variable, say `r`, then we bind the result of executing `var` 739 | to the fresh name `,r`. 740 | 741 | Whence: `` `(⋯,var⋯,var⋯) `` 742 | 743 | ``⇒ (let ((r (gensym))) `(let ((,r ,var)) ⋯,r⋯,r⋯))``. 744 | 745 | Note that the name `r` is outside the backquote; it is part of code that is run 746 | at macro expansion time, not runtime. The value of the final `let` is then the backquoted 747 | matter, which makes *no* reference to `r`, but instead makes use of the name it 748 | refers to, `,r`. Neato! 749 | 750 | Ex., remove repeated execution from ``(defmacro twice (var) `(list ,var ,var))``. 751 | 752 | - Test that you don't have accidentally variable capture by passing in an insert 753 | statement and see how many times insertions are made. 754 | 755 | - Macros that *intentionally* use variable capture as a feature, rather than a bug, 756 | to provide names available in the macro body are called ‘anaphoric macros’. 757 | 758 | E.g., `(split list no yes)` provides the names `head, tail` in the `yes` body 759 | to refer to the head and tail of the given `list`, say via a `let`, but not so in the 760 | `no` argument for when `list` is empty. Whence, elegant pattern matching on lists. 761 | 762 | Exercise: Define `split`. 763 | 764 | \vfill 765 | 766 | 767 | 768 | 769 | # `read` and `print` 770 | 771 | ‘Reading’ means parsing an expression in textual form and producing a lisp object. 772 | E.g., this is a way to load a lisp file. ‘Printing’ a lisp object mean producing 773 | a textual representation. These operations, in lisp, are mostly inverse. 774 | 775 | The `read-from-string` command works just like the `read` command, but 776 | lets us read a lisp object from a string instead of directly from the console. 777 | 778 | (defun sum-two () 779 | (let (fst snd) 780 | (setq fst (read)) 781 | (setq snd (read)) 782 | (+ (eval fst) (eval snd)) 783 | ) 784 | ) 785 | 786 | ;; Run (sum-two) with inputs (+ 1 2) and (* 3 4) ;-) 787 | 788 | Lisp makes writing a REPL astonishingly easy: “Loop as follows: 789 | Print the result of evaluating what is read at the prompt.” 790 | 791 | (loop (print (eval (read)))) ;; Beautiful ♥‿♥ 792 | 793 | - `loop` merely loops forever. 794 | 795 | The `print` and `read` commands work on all kinds of data, such as lists of data 796 | structures. Hence, we must use quotes if we want to read a string rather than a 797 | symbol, for example. 798 | 799 | A major problem with this REPL is that `eval` executes any, potentially malicious, 800 | Lisp command entered by the user. Ideally one checks the read lisp object is 801 | safe —say, it is one of some allowable commands— and only then evaluates it. 802 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-merlot --------------------------------------------------------------------------------