Lisp was invented by John McCarthy in 1958 while he was at the Massachusetts Institute of Technology (MIT).
McCarthy published it’s design in a paper entitled “Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I” (HTML|PDF) in 1960, in which he showed that with a few simple operators and a notation for functions, one can build a Turing-complete language for algorithms.
Lisp (historically, LISP) is a family of computer programming languages with a long history and a distinctive, fully parenthesized Polish prefix notation.
Originally specified in 1958, Lisp is the second-oldest high-level programming language in widespread use today.
Lisp has changed a great deal since its early days, and a number of dialects have existed over its history.
Today, the most widely known general-purpose Lisp dialects are Common Lisp and Scheme.
1955 | 1960 | 1965 | 1970 | 1975 | 1980 | 1985 | 1986 | 1990 | 1995 | 2000 | 2005 | 2012 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Lisp 1.5 | Lisp 1.5 | ||||||||||||
Maclisp | Maclisp | ||||||||||||
ZetaLisp | ZetaLisp | ||||||||||||
NIL | NIL | ||||||||||||
Interlisp | Interlisp | ||||||||||||
Common Lisp | Common Lisp | ||||||||||||
Scheme | Scheme | ||||||||||||
ISLISP | ISLISP |
(function parameter second-parameter third-parameter)
CL-USER> (+ 3 7 5)
15
CL-USER> (first (list "a" "b"))
"a"
Quoting to prevent evaluation (equivalent ways):
(quote (a b c))
'(a b c)
(list t nil 0 0.5 1.0d0 #C(0 1) 'symbol #'function :keyword)
CL-USER> (cons 1 2)
(1 . 2)
(list 42 69 613)
(cons 42 (cons 69 (cons 613 nil)))
Common Lisp is a general-purpose, dynamic multi-paradigm programming language.
Common Lisp includes CLOS, an object system that supports multimethods and method combinations.
Facilitates evolutionary and incremental software development, with iterative compilation* into efficient run-time programs.
*) With optional type annotation and casting, which can be added later when profiling and optimising. The compiler can be told on a per-module or per-function basis which type safety level is wanted, using optimize declarations.Extensible through standard features such as Lisp macros` and reader macros#.
`) Compile-time code rearrangement accomplished by the program itself.Function definition:
(defun name (parameter*)
"Optional documentation string."
body-form*)
DOCUMENTATION
function.DEFUN
consists of any number of Lisp expressions. They will be evaluated in order when the function is called and the value of the last expression is returned as the value of the function. The RETURN-FROM
special operator can be used to return immediately from anywhere in a function.First-class functions are functions that take other functions as arguments or return functions.
To be able to pass functions around, you need to refer to a function value of a symbol using function
:
CL-USER> (function >)
#<FUNCTION >>
CL-USER> #'>
#<FUNCTION >>
The #' notation is a Common Lisp shortcut way of the above and more commonly used.
Sort a list using the > and < function:
CL-USER> (sort (list 5 2 6 3 1 4) #'>)
(6 5 4 3 2 1)
CL-USER> (sort (list 5 2 6 3 1 4) #'<)
(1 2 3 4 5 6)
Sort a list according to the first element of each sub-list:
CL-USER> (sort (list '(9 "A") '(3 "B") '(4 "C")) #'< :key #'first)
((3 "B") (4 "C") (9 "A"))
Sort by the second element of each sub-list:
CL-USER> (sort (list '(9 "A") '(3 "B") '(4 "C")) #'string< :key #'second)
((9 "A") (3 "B") (4 "C"))
The function #'second is an alias for #'cadr, whichSort trie branches with a predicate.
(defun sort-trie-branch (trie predicate &key (key #'key) (stable nil))
"Sort a trie node’s branches with a predicate function."
(let ((branches (copy-list (branches trie)))
(sort (if stable #'stable-sort #'sort)))
(setf (branches trie)
(funcall sort branches predicate :key key))
trie))
Using this function while traversing the trie, the whole tree can be sorted.
But this is a bad example for functional programming. Can you tell why?
It modifies the trie in-place, which is unacceptable in functional programming.Defined by lambda expressions:
(lambda (parameters) body)
One way to think of LAMBDA
expressions is as a special kind of function name where the name itself directly describes what the function does. This explains why you can use a LAMBDA
expression in the place of a function name with #':
(funcall #'(lambda (x y) (+ x y)) 2 3) ⇒ 5
You can even use a LAMBDA
expression as the "name" of a function in a function call expression. If you wanted, you could write the previous FUNCALL
expression more concisely:
((lambda (x y) (+ x y)) 2 3) ⇒ 5
An important use of LAMBDA
expressions is in making closures, functions that capture part of the environment where they're created.
(map 'list #'* '(1 2 3) '(4 5 6)) ⇒ (4 10 18)
(reduce #'* '(1 2 3 4 5)) ⇒ 120
MAPC
, MAPCAR
, MAPCAN
, MAPL
, MAPLIST
and MAPCON
mapc function &rest lists+ ⇒ list-1
mapcar function &rest lists+ ⇒ result-list
mapcan function &rest lists+ ⇒ concatenated-results
mapl function &rest lists+ ⇒ list-1
maplist function &rest lists+ ⇒ result-list
mapcon function &rest lists+ ⇒ concatenated-results
Left fold without initial value |
|
---|---|
Right fold without initial value |
|
Left fold |
|
Right fold |
|
|
REMOVE-IF
:(remove-if inverted-pred list)
(remove-if (complement pred) list)
(remove-if-not pred list)
Note! The function remove-if-not
has been deprecated in favor of the equivalent remove-if
where the predicate is complemented.
Zip and Unzip can be made using Mapcar:
CL-USER> (defparameter nums '(1 2 3))
CL-USER> (defparameter tens '(10 20 30))
CL-USER> (defparameter firstname "Alice")
;; Zips
CL-USER> (mapcar #'list nums tens)
((1 10) (2 20) (3 30))
CL-USER> (mapcar #'list nums tens (coerce firstname 'list))
((1 10 #\A) (2 20 #\l) (3 30 #\i)) — truncates on shortest list
;; Unzips
CL-USER> (apply #'mapcar #'list (mapcar #'list nums tens (coerce firstname 'list)))
((1 2 3) (10 20 30) (#\A #\l #\i))
defclass
(defclass person ()
((name :accessor person-name
:initform 'bill
:initarg :name)
(age :accessor person-age
:initform 10
:initarg :age)))
make-instance
(make-instance 'person :name 'jill :age 100)
It’s often a good idea to define your own constructor functions, rather than call make-instance
directly, because you can hide implementation details and don't have to use keyword parameters for everything:
(defun make-person ((name 'bill) (age 10))
(make-instance 'person :name name :age age))
(make-person 'jill 100)
initialize-instance
The definition of DEFMACRO
:
(defmacro name (parameter*)
"Optional documentation string."
body-form*)
...is very similar to that of DEFUN
.
(defmacro do-primes ((var start end) &body body)
`(do ((,var (next-prime ,start) (next-prime (1+ ,var))))
((> ,var ,end))
,@body))
A useful way to think about the backquote syntax is as a particularly concise way of writing code that generates lists. For instance, `(,a b)
might be read as (list a 'b)
Read Macros Defining Your Own for more information.
The book “Practical Common Lisp” by Peter Siebel
If you feel confident using basic Emacs editing command, I recommend using SBCL with Emacs and SLIME. Otherwise I recommend installing Clozure CL.
Also install Quicklisp if using either Common Lisp implementation.
SBCL is acronym for Steel Bank Common Lisp.
SLIME is acronym for Superior Lisp Interaction Mode for Emacs.
➜ sudo port install sbcl
There are two alternative methods of installing SLIME.
Install SLIME with MacPorts or apt-get
(will also install emacs and Emacs.app)
➜ sudo port install slime
Copy dot.emacs into ~/.emacs
to have the settings for SLIME as described by the port install
There are two alternative methods of installing SLIME.
Install Quicklisp (see instructions)
Type within Lisp REPL:
* (ql:quickload "quicklisp-slime-helper")
Add this to your ~/.emacs:
(load (expand-file-name "~/quicklisp/slime-helper.el"))
;; Replace "sbcl" with the path to your implementation
(setq inferior-lisp-program "sbcl")
➜ open -a /Applications/MacPorts/Emacs.app
OR
➜ open -a /Applications/Aquamacs.app
Type in Emacs or Aquamacs:
meta-x slime
(meta key is usually mapped to option, tapping ESC before the key also works)
1) Check out Clozure Common Lisp from the Subversion [~2-3 min]
➜ svn co http://svn.clozure.com/publicsvn/openmcl/release/1.8/darwinx86/ccl
➜ cd ccl
➜ ./dx86cl64 --no-init
Welcome to Clozure Common Lisp Version 1.8-r15286M (DarwinX8664)!
? (rebuild-ccl :full t)
; lots of output
? (quit)
➜ sudo cp scripts/ccl64 /usr/local/bin
➜ export CCL_DEFAULT_DIRECTORY="`pwd`" # put this into .zshrc or .bashrc
➜ echo $CCL_DEFAULT_DIRECTORY
/Users/peterhil/Programming/Lisp/ccl
➜ rehash # if using zsh
➜ ccl64
Welcome to Clozure Common Lisp Version 1.8-r15485M (DarwinX8664)!
? (require :cocoa-application)
; lots of output
➜ open Clozure\ CL64.app/
Install SLIME as described in SBCL instructions above.
In Emacs or Aquamacs type:meta-- meta-x slime RETURN
ccl64
(meta key is usually mapped to option, tapping ESC before the key also works)
➜ cd ~
➜ curl -O http://beta.quicklisp.org/quicklisp.lisp
➜ sbcl --load quicklisp.lisp # replace sbcl with ccl64 if using Clozure CL
* (quicklisp-quickstart:install)
; Try to install some package (CL-PPCRE is a regexp library written by Edi Weitz):
* (ql:quickload "cl-ppcre")
; Search for available libraries:
* (ql:system-apropos "vecto")
; Add Quicklisp to your Lisp's init file:
* (ql:add-to-init-file)
; Done
* (quit)