elisp
Table of Contents
1 Basic
1.1 Char Representation
?\U, ?\u, ?\x, ?\101?^I, ?\C-I, ?\M-I ?\S-I
1.2 Symbol
Symbols are a fundamental type of data in Lisp and are used extensively. A symbol in Lisp is a stand-alone word.
Creating Symbols
(symbol-name 'foo) ;; returns a newly-allocated, uninterned symbol whose name is NAME (which must be a string) (make-symbol "foo") ;; returns the interned symbol. If OBARRAY is omitted, the value of the global variable 'obarray' is used (intern "foo" other-obarray) ;; returns the symbol in OBARRAY whose name is NAME, or‘nil’ if OBARRAY has no symbol with that name. (intern-soft "foo") ;; map on obarray (mapatoms functions &optional obarray) ;; deletes SYMBOL from the obarray OBARRAY (unintern symbol obarray)
Special Symbols
'nil, 't
1.3 Sequence
an ordered set of elements
lists
(eq () nil) ; -> t (A 2 "A") ; A list of three elements.
A cons cell is made for each element. The CAR slot of the cons cell holds the element, and its CDR slot refers to the next cons cell of the list, which holds the next element in the list. The CDR slot of the last cons cell is set to hold 'nil'.
1.4 Special Forms
Special forms are something like built-in macros, examples: if, progn
1.5 defs
defconst:defconst symbol value [doc-string], should not be changed by the user or by other programs.defvar:defvar symbol [value [doc-string]], define global variablesdefun: define global functionslet: define local variablesflet: define local functionsdefstructcl-defgeneric: replacement fordefmethod, define generic functions
1.6 examples
(defvar bar 23 "The normal weight of a bar.") (defconst float-pi 3.141592653589793 "The value of Pi.") ;; (let ((variable value) ;; (variable value) ;; …) ;; body…) (let ((a 5) (b 6)) (+ a b)) ;; (flet ((function_name (arguments) ;; ...function body...)) ;; ...body...) (flet ((f (n) (+ n 10)) (g (n) (- n 3))) (g (f 5)))
1.7 Function Pointer[#']
#'sqrt will be converted to (function sqrt) by Lisp reader
2 Print & Read
2.1 Print
print: computer-friendly printprin1: likeprintbut not print#/newlineprinc: human-friendly printprin1-to-string
2.2 Read
read: computer-friendly readread-line: human-friendly read(common lisp)
2.3 terpri newline
3 Code & Data
'(+ 1 2) ;data mode (+ 1 2) ;code mode (defvar *foo* '(+ 1 2)) (eval *foo*)
4 List
4.1 List Functions
cons
When you call cons, the Lisp compiler typically allocates a small chunk of memory, the cons cell,
that can hold two references to the objects being linked.
(cons 'chicken 'cat) ; -> (CHICKEN . CAT) The dot in the middle makes this a cons cell (cons 'chicken 'nil) ; -> (CHICKEN) nil is a special symbol that is used to terminate a list in Lisp (cons 'chicken ()) ; -> (CHICKEN) (cons 'pork '(beef chicken)) ; -> (PORK BEEF CHICKEN) (cons 'pork (cons 'beef (cons 'chicken ()))) ; -> what is really happening underneath
In Lisp, a chain of cons cells and a list are exactly the same thing.
car and cdr
(car '(pork beef chicken)) ; -> PORK (cdr '(pork beef chicken)) ; -> (BEEF CHICKEN) (car (cdr '(pork beef chicken))) ; -> BEEF (cadr '(pork beef chicken)) ; -> BEEF shortcut
others
For convenience, Common Lisp has many functions built on top of the basic three,
cons, car, and cdr
(list 'pork 'beef 'chicken) ; does the dirty work of creating all the cons cells '(pork beef chiken) ; the same
4.2 Dotted List
a list without nil
(cons 1 (cons 2 3)) ; -> (1 2 . 3)
This dot is basically Lisp’s way of saying, “I tried to print this structure you entered using list notation, but the last item in the list didn’t contain the usual nil I expected; instead, it contained 3.
alternative syntax for cons
Another way of thinking about this dot notation is to consider it as simply an alternate syntax for the cons command
'(1 . (2 . (3 . nil))) ; -> (1 2 3)
elegant represent pairs
(cons 2 3) -> (2 . 3)
4.3 Circular Lists
(defparameter foo '(1 2 3)) (setf (cdddr foo) foo)
4.4 Association List(alist)
They are not a very efficient way to store and retrieve data.
(defvar *dict* '((key1 value1) (key2 value2) (key3 value3))) (push '(key1 . value4) *dict*) ; add new item to the front (assoc 'key1 *dict*) ; to look up from the front and returns the first one
5 Data Structures
5.1 Arrays
(setf primes [2 3 5 7 11 13]) (arrayp primes) ; -> T (aref primes 1) ; -> 3 (setf (aref primes 1) 5) ; primes -> [2 5 5 7 11 13]
5.2 Hash Tables
(setf x (make-hash-table)) (gethash 'nope x) ; -> nil (setf (gethash 'nope x) 5)
5.3 Return Multiple Values
(defun foo () (values 3 7)) (multiple-value-bind (a b) (foo) (* a b))
5.4 Structure(OOP)
(defstruct person name age gender) (setf john (make-person :name "john" :age 37 :gender "male")) (person-age john) (setf (person-age john) 38)
6 Generic Functions
6.1 Creating Generic Functions
(cl-defgeneric add ((a number) (b number)) (+ a b)) (cl-defgeneric add ((a list) (b list)) (append a b)) (add 3 4) (add '(a b) '(c d))
7 Functional Programming
7.1 Pros
- Reduces Bugs(no side effect)
- More Compact
- More Elegant(try to keep 80% function "clean")
7.2 Cons
Performance has always been a huge concern with functional programs. Functional programmers have developed optimization techniques that can solve the vast majority of performance problems. These include memoization, tail call optimization, lazy evaluation, and higher-order programming
Memoization
Memoization makes use of closures. Lexical variables are used for memoization.
Tail Call Optimization
(defun my-length (lst) (if lst (1+ (my-length (cdr lst))) 0)) ; inefficient (my-length '(a b c d)) (defun my-length (lst) (labels ((f (lst acc) (if lst (f (cdr lst) (1+ acc)) acc))) (f lst 0))) ; tail call optimization
When a function in Lisp calls itself as its very last action, we call this action a tail call. A smart Lisp compiler, when seeing a tail call, can then say to itself, “Hey, since I don’t need to do anything more after calling f again, I can just go straight to f, without needing to put the current program context on the stack.” This is actually similar to performing a a longjmp in C++.
7.3 Summary
- Programs written in the functional style always give the same result when they are given the same values in their arguments.
- Functional programs do not contain side effects.
- A good strategy for writing Lisp programs is to break them into a clean, functional part and a dirty, imperative part.
8 Meta Programming
8.1 Quasiquoting[`]
Quasiquoting is a technique that allows you to insert small bits of computer code into larger pieces of data.
`(there are ,(+ 1 4) apples) ; -> there are 5 apples `(there are (+ 1 4) apples) ; -> there are (+ 1 4) apples
8.2 Macro programming
A Simple Macro
(let ((foo (+ 2 3))) (* foo foo)) (defmacro let1 (var val &rest body) `(let ((,var ,val)) ,@body)) ; get rid of the superfluous parentheses (let1 foo (+ 2 3) (princ "Lisp is awesome!") (* foo foo)) (macroexpand '(let1 foo (+ 2 3) (* foo foo))) ; for debug
9 Useful Functions & Marcos
ash: shiftcar,cdr,cons,cadr,cadadr, …defvar,setq,setf,letcl-flet: defining local function,cl-labels(),'(),'nil,nilare all falsemapcar,applysubstitute-if- set ops:
set-difference,intersection,remove-duplicates
9.1 Generic Functions
length, find-if, count, position, some, every, reduce, map/mapcar
subseq, sort
(length '(a b c)) (length "blub") (find-if #'numberp '(a b 5 d)) (count 4 [1 4 4 5]) (some #'numberp '(a b 5 d)) (every #'numberp '(a b 5 d)) (map 'list (lambda (x) (* 2 x)) '(3 4 6 5 2)) (reduce #'+ '(3 4 6 5 2)) (subseq "america" 2 6) (sort '(5 8 2 4 9 3 6) #'<)
9.2 conditionals
if, when, unless, cond, or, case, and
when, unless
Eliminates the pain of progn
cond
The cond form is the classic way to do branching in
Lisp. Through the liberal use of parentheses, it allows for an
implicit progn, can handle more than one branch, and can even
evaluate several conditions in succession.
- using last
tcondition to guarantee that at least the last branch will be evaluated.
case
otherwiselikedefaultin other language
eq, equal, etc.
eq: reference comparisonequal: content comparison (look the same)eql: likeeq, but handles comparisons of numbers and characters (compare these types by value)equalp:likeequal, and it can compare strings with different capitalizations and
can compare integers against floating-point numbers
(equal 'apple 'apple) ; -> T (equal (list 1 2 3) (list 1 2 3)) ; -> T (eq (list 1 2 3) (list 1 2 3)) ; -> NIL (eq 3.4 3.4) ; -> NIL (eql 3.4 3.4) ; -> T (equalp "Bob Smith" "bob smith") ; -> T strange! (equalp 0 0.0) ; -> T
9.3 push/assoc idiom
The assoc command always returns the first item it finds in a list. Using
the push and assoc commands together allows us to pretend that values in
an alist are changing, while still preserving old values(keep history of all
old values).
9.4 loop Macro
(loop for i from 2 below 5 sum i) (loop for i in '(100 20 3) sum i) (loop for i below 5 do (print i) sum i) ; do other things (loop for i below 10 when (oddp i) sum i) ; do when ... (loop for i from 0 do (print i) when (= i 5) return 'finished) ; break loop (loop for i in '(2 3 4 5 6) collect (* i i)) ; return a list (loop for x below 10 for y below 10 collect(+ x y)) ; -> (0, 2, 4, 6, ...) (loop for x below 10 collect (loop for y below 10 collect (+ x y))) ; Cartesian product (loop for i from 0 for day in '(monday tuesday wednesday thursday friday saturday sunday) collect (cons i day)) ; -> ((0 . monday) (1 . tuesday) ...)
9.5 format function
(format "Add onion rings for only %.2f dollars more!" 1.5)
10 Profiling
see benchmark.el
11 Loading Process
- add to
load-path load-fileprovide,require
11.1 autoload
Things that can be auto-loaded generally involve anything "definable", such as functions, macros, major or minor modes, groups, classes, and so on.
(autoload 'some-function "some-file") ;;;###autoload (defun my-function () ;; Source code... ) ;;;###autoload (require 'helm)
11.2 Eval after load
(with-eval-after-load 'helm ;; Code )