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 variables
  • defun: define global functions
  • let: define local variables
  • flet: define local functions
  • defstruct
  • cl-defgeneric: replacement for defmethod, 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 print
  • prin1: like print but not print #/newline
  • princ: human-friendly print
  • prin1-to-string

2.2 Read

  • read: computer-friendly read
  • read-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: shift
  • car, cdr, cons, cadr, cadadr, …
  • defvar, setq, setf, let
  • cl-flet: defining local function, cl-labels
  • (), '(), 'nil, nil are all false
  • mapcar, apply
  • substitute-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 t condition to guarantee that at least the last branch will be evaluated.

case

  • otherwise like default in other language

eq, equal, etc.

  • eq: reference comparison
  • equal: content comparison (look the same)
  • eql: like eq, but handles comparisons of numbers and characters (compare these types by value)
  • equalp:like equal, 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-file
  • provide, 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
  )

11.3 use-package