wiki/articles/lisp.md

4.8 KiB
Raw Blame History

Lisp

Lisp (LISP for List Processing) is a family of programming languages that share common features such as the S-Expression syntax, powerful metaprogramming capabilities with macros adding extensibility, the use of lists as the principal data structure, first-class functions (lambdas), garbage collection and recursion.

Lisp was created in 1958 by John McCarthy, making Lisp on of the oldest languages used today, second to Fortran. Originally Lisp didn't use the now ubiquitous S-Expression syntax but M-Expressions (as used in the Lisp 1.5 manual), however S-Expressions turned out to be more popular and Lisps began using it.

Unlike other languages at the time and also modern languages, Lisp is homoiconic, that is, Lisp source code is data that can be manipulated by the program itself. This gives Lisp powerful metaprogramming capabilities through the use of macros which modify the program data at compile time. Therefore, Lisp source code directly represents the program as a tree without extra superfluous syntax (as in mainstream programming languages).

A Lisp can be built on a basic set of primitives such as cons, car, cdr, lambda, apply, eval, eq, quote and others (as described in the Lisp 1.5 manual). Since it is based on the lambda calculus a Lisp could also be built in terms of lambdas. For example, using Church encoding this is how cons cells could be implemented using only lambdas:

(define (cons x y) (lambda (z) (z x y)))
(define (car p) (p (lambda (x y) x)))
(define (cdr p) (p (lambda (x y) y)))

(cdr (cons 'A 'B))                      ; ==> B
(car (cons 'A 'B))                      ; ==> A
(car (cdr (cons 'A (cons 'B 'C))))      ; ==> B
(cdr (cdr (cons 'A (cons 'B 'C))))      ; ==> C

By using lambdas you could also implement arithmetic from scratch, including numbers themselves.

A PDF of the original Lisp 1.5 manual can be found here: https://www.lispmachine.net/books/LISP_1.5_Programmers_Manual.pdf. Head to page 13 for enlightenment.

Cons cells and Lists

A list in Lisp is composed of cons cells which have two fields: the contained value of the cell known as car and a pointer to the next cell known as cdr. To mark the end of a list, a special sentinel value, NIL is used, which represents an empty list.

Here's cons cell:

    +---+---+    
    | O | O-|----> cdr
    +---+---+    
      |          
     `'´         
     car

To create a cell, the builtin function cons is used:

(cons 1 2)          ; 1 and 2 are the car and cdr respectively
(car (cons 1 2))    ; ==> 1
(cdr (cons 1 2))    ; ==> 2
;; Also some Lisps accept the "dotted pair" notation as a shorthand:
(1 . 2)

And here's a list:

              cdr           cdr           cdr           cdr
    +---+---+     +---+---+     +---+---+     +---+---+    
    | O | O-|---->| O | O-|---->| O | O-|---->| o | O-|----> NIL
    +-|-+---+     +---+---+     +---+---+     +---+---+    
 car  |        car  |        car  |        car  |          
     `'´           `'´           `'´           `'´         
      20            "Lisp"        (1 2)         39 

Creating lists:

;; Using cons:
(cons 20 (cons "Lisp" (cons '(1 2) (cons 39 '()))))
;; In cons dotted pair notation:
(20 . ("Lisp" . ('(1 2) . (39 . NIL))))
;; Using quote:
'(20 "Lisp" '(1 2) 39)
;; Most Lisps provide a `list` function:
(list 20 "Lisp" '(1 2) 39)

Of course, cons cells are not limited to just lists, they can be nested and represent trees. Just read any Lisp source code for proof, you're seeing the source encoded in a tree, directly by using S-Expressions. But here is something more immediate:

;; (20 * 2 + 16) / 30 * 5
(cons '* (cons (cons '/ (cons (cons (cons '+ (cons '* (cons 20 2)) 16)) 30)) 5))
;;
;;                       (*)
;;                      /   \
;;                   (/)     5
;;                  /   \
;;                (+)    30
;;               /   \
;;            (*)     16
;;           /   \
;;         20     2
;; Or simply equivalent to this Lisp expression:
(* (/ (+ (* 20 2) 16) 30) 5)

Lisp languages

  • Scheme: created by the hackers Guy Steele and Gerald Sussman in 1975 at the MIT.
  • PicoLisp: another minimalistic Lisp, internally uses only cells.
  • Common Lisp: Big for Lisp standards (still better and smaller than "modern" languages), is also the most used Lisp today.
  • Dylan: dynamic, most notably it has a ALGOL-style syntax more similar to modern languages instead of a S-Expression-based syntax.
  • Clojure: runs on the JVM (Java Virtual Machine), does not have cons, car or cdr. Basically Java under a Lisp skin.
  • ...

See Also