LISP Notes

This list includes all Lisp forms needed in this class.


Atoms

Unlike other languages, LISP has only a few primitive data types, called atoms.

t                       true
nil                     false
A, Cow, moo             symbols
1, 2, 3                 numbers
"hey there"             strings

Quoted Forms

A quoted form is a LISP expression that is not immediately evaluated. This is often used to create list literals.

'abc                    Unevaluated symbol
'(1 2 3)                The list (1 2 3), which is not evaluated.  Ex:
                                 (+ 1 2)  -> 3
                                '(+ 1 2)  -> (+ 1 2)

Boolean expressions

(eq x y) returns t if x and y are the same number or the same list. Note: there are other equality tests (eql, equals, etc.). For 334, the distinctions should be not important and eq should sufficient for the problems we do.

                            (eq 1 1)  ->  t
                            (eq 1 2)  ->  nil
                          (eq 'A 'A)  ->  t
                          (eq 'A 'B)  ->  nil
                        (eq nil nil)  ->  t

(< x y) is an arithmetic comparison. Other comparisons include: >, >=, or, and, not.

                            (< 1 2)  ->  t
                            (< 2 1)  ->  nil

(atom x) returns t if x is an atom and nil if x is a list.

                          (atom 'A)   ->  t
                          (atom nil)  ->  t
              (atom (car '(A nil)))   ->  t
              (atom (cdr '(A nil)))   ->  nil

(member x l) returns nil if x is not in the list, or t (or some other non-nil value) if x is in the list.

                 (member 'A '(A B))   ->  t
                 (member 'C '(A B))   ->  nil

Arithmetic expressions

(+ e1 ... en) sums the numbers e1en. *, -, / operators work similarly.

                            (+ 1 2 3)  -> 6

Other operators include mod, sin, cos, etc.

                            (mod 7 3)  -> 1

Lists

nil is the empty list.

(cons x ls) the list containing x, followed by the elements in list ls.

                            (cons 'A nil)   -> (A)
                            (cons 'A (B))   -> (A B)
                            (cons nil nil)  -> (nil)

(car ls) is the first element of the list ls.

                            (car '(A B C))  -> A
                    (car (cons 'A '(B C)))  -> A

(cdr ls) is the list ls, excluding the first element.

                                 (cdr nil)  -> nil
                            (cdr '(A B C))  -> (B C)
                    (cdr (cons 'A '(B C)))  -> (B C)

(append l1 l2) is the list containing the elements from l1, followed by the elements from l2.

                     (append '(A B) '(C D)) -> (A B C D)

(length ls) is the length of the list.

                              (length nil)  -> nil
                         (length '(A B C))  -> 3

Conditionals

(cond (p1 e1) ... (pn en)) evaluates each pi in order until it finds a true guard. It then evaluates the expression for that guard:

            (cond ((eq 0 1) 2) (t 3))  -> 3
            (cond ((eq 0 0) 2) (t 3))  -> 2

(if p e1 e2) is more readable syntax for a cond that defines a familiar “if-then-else” structure. Use cond if you have more than two conditions to test.

            (if (eq 0 1) 2 3)  -> 3
            (if (eq 0 0) 2 3)  -> 2

Function definitions

(defun f ls body) defines a function named f, with arguments ls.

                    (defun fact (x) 
                            (cond ((eq x 0) 1)
                                  (t (fact (- x 1)))))

                    (defun mult(x y) (* x y))

(lambda ls body) is an anonymous function expression (aka, a lambda expression).

                    ((lambda (x) (* x x)) 3) -> 9

Higher-order Operations

A higher-order function is a function that takes another function as input. Since functions are first-class values in LISP, higher-order functions are not special in LISP. Nevertheless, a small number of fundamental higher-order functions are used frequently in LISP programs.

(mapcar #'f l) maps the function f over the elements of list l, returning a new list.

                            (mapcar #'atom '(A (2 3) B)) -> (t nil t)
                            (mapcar #'(lambda (x) (+ x 2)) '(1 3)) -> (3 5)

The #’ in front of a lambda or function name extracts the “functional object” assocated with that function or lambda expression. The functional object for a function “f” records the number of arguments expected by f, the code for the body of f, etc.

(apply #'f (e1 ... en)) is equivalent to (f e1 ... en).

                            (apply #'* '(2 2 3))  -> 12
                            (apply #'fact '(1 2 3 4))  -> (1 2 6 24)

(funcall #'f e1 ... en) is equivalent to (f e1 ... en).

                            (funcall #'* 2 2 3)  -> 12
                            (funcall #'fact 1 2 3 4)  -> (1 2 6 24)

For all of these higher-order operations, note that you do not need #' in front of a parameter name that stores a function you have passed into a function. You only need #’` when you refer directly to the symbol for a function definition:

			(defun reverse-map (f l) 
			       (mapcar f (reverse l)))
			(reverse-map #'- '(1 2 3))       ->   (-3 -2 -1)

Impure Features

Here for completeness only. You should not use these in your programs unless explictly told to do so.

(defvar ls '(a b c)) defines a variable ls with value '(a b c).

(rplaca ls x) updates ls to be '(x b c).

(rplacd ls (x)) updates ls to be '(a x).

  • CSCI 334: Principles of Programming Languages, Spring 2022

CSCI 334 website repository, Spring 2022

Powered by Bootstrap 4 Github Pages