In: lisp, programming, language.

Common LISP (programming language)

Lisp is the second-oldest high-level programming language after Fortran and 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.
Lisp was invented by John McCarthy in 1958 while he was at the Massachusetts Institute of Technology (MIT).

Wiki

Awesome

Hyperpolyglot

Implementations

Tools

Useful libraries:

Generative art:

Learn

Video

NOTES

Numbers

(+ 1 2) ;; => 3

#xFF   ;; => 255
;; base 16
#16rFF ;; => 255
#16r10 ;; => 16
;; base 32
#32r10 ;; => 32

;; For numbers, use =
(=   5 5.0) ;; => T
(eq  5 5.0) ;; => NIL
(eql 5 5.0) ;; => NIL

(type-of 10)  ;; => (INTEGER 0 ...)
(type-of 1.5) ;; => SINGLE-FLOAT
(type-of -5)  ;; => FIXNUM

(abs -3)  ;; => 3
(float 1) ;; => 1.0

(ceiling 1.45) ;; => 2
(floor 1.45)   ;; => 1
(round 1.45)   ;; => 1

(ffloor 2.5)    ;; => 2.0 0.5
(fround 2.5)    ;; => 2.0 0.5
(ftruncate 2.5) ;; => 2.0 0.5

(rem -10 3) ;; => -1
(mod -10 3) ;; => 2

(max 1 2 3) ;; => 3
(min 1 2 3) ;; => 1

;; a random nr from 0 up-to 100
(random 100)

;; increment INCF
(let ((x 1)) (incf x)) ;; => 2
;; decrement DECF
(let ((x 1)) (decf x)) ;; => 0

most-positive-fixnum ;; => 4611686018427387903
most-negative-fixnum ;; => -4611686018427387904

Cons pairs & Lists

A cons cell, also known as a dotted pair, is simply a pair of two objects.

Common Lisp, and other languages in the LISP family, make extensive use of lists, but Common Lisp doesn’t actually include a primitive list datatype.
The lists exist only by convention.

;; to create a CONS pair
(cons 1 2) ;; => (1 . 2)

;; can also be expressed as
'(1 . 2) ;; => (1 . 2)

(type-of (cons 1 2)) ;; => CONS

;; a nested cons pair
(cons 1 (cons 2 3))
;; => (1 2 . 3)

;; this is now a list, by convention
(cons 1 (cons 2 nil)) ;; => (1 2)

;; shorter way of declaring a list
(list 1 2) ;; => (1 2)

;; and even shorter
'(1 2) ;; => (1 2)

;; equivalent with
(quote (1 2)) ;; => (1 2)

;; for lists, strings, and bit-vectors use EQUAL
(equal '(1 2) '(1 2))

To access cons and lists, you have a ton of functions, which is expected for a LISt Processor language:

(car '(1 . 2))  ;; => 1
(car '(1 2))    ;; => 1

(cdr '(1 . 2)) ;; => 2
(cdr '(1 2))   ;; => (2)

(cdr '(1 2 3))  ;; => (2 3)
(rest '(1 2 3)) ;; => (2 3)

;; prettier names
(first '(1 2)) ;; => 1
(last '(1 2))  ;; => (2)
(butlast '(1 2 3)) ;; => (1 2)

;; also: first, second, third, fourth, fifth, sixth, seventh, eighth, ninth, tenth
;; first is functionally equivalent to car, second is functionally equivalent to cadr, third is functionally equivalent to caddr, and fourth is functionally equivalent to cadddr
(setq li '(1 2 3 4))
(second li) ;; => 2
(third li)  ;; => 3
(fourth li) ;; => 4

;; check if variable is a list
(listp li)
;; the length of a list
(list-length li)

;; the tail of list beginning with the first matching element
(member 4 '(1 2 3 4 5)) ;; => (4 5)
;; Sequence func: count how many times is found
(count 3 '(1 3 3 3 3)) ;; => 4

;; copy a list
(copy-list li)

Changing lists:

;; concatenate lists
(append (list 1 2) (list 3 4)) ;; => (1 2 3 4)
;; also
(concatenate 'list '(1 2) '(3 4)) ;; => (1 2 3 4)

(defparameter list1 '(1 2 3))
(push 0 list1) ;; => (0 1 2 3)
(pop list1)    ;; => (1 2 3)

;; insert fist and return new list
(list\* 0 list1)
;; => (0 1 2 3)

;; reverse a list
(reverse list1)
;; => (3 2 1)

Property Lists (Plists)

By convention, you can define lists that represent kind of key to value mappings.
A property list, or Plist, is a regular list in which alternating values are interpreted as keys and their associated values.

;; define an object with 3 keys and 3 values
(defparameter *3dobj* (list 'x 10 'y 5 'z 25))

;; get value of X
(getf *3dobj* 'x)
;; get and use default
(getf *3dobj* 'wrong -1)

;; set new value of X
(setf (getf *3dobj* 'x) 15)

;; create new plist with extra keys-values
(defvar *new-3dobj* (list* 'j -1 *3dobj*))

Association Lists (ALists)

By convention, you can define lists that represent kind of key to value mappings.
An association list, or alist is a regular list whose elements are dotted pairs in which the car of each pair is the key and the cdr of each pair is the associated value.

;; define an object with 3 keys and 3 values
(defparameter \*3dobj\* (list (cons 'x 10) (cons 'y 5) (cons 'z 25)))

;; ZIP keys and values
(pairlis '(a b c) '(2 4 8))
;; => ((C . 8) (B . 4) (A . 2))

;; get a key-value pair
(car (member 'z \*3dobj\* :key 'car)) ;; => (z . 25)

;; shorter
(assoc 'y \*3dobj\*) ;; => (y . 5)

;; create new alist with extra keys-values
(acons 'c 3 '((a . 1) (b . 2)))
;; => ((c . 3) (a . 1) (b . 2))

Strings

(write "Hello")
(print "Hello")

(char "a-b_c" 0) ;; => #\a
(char "a-b_c" 1) ;; => #\-
(char "a-b_c" 3) ;; => #\_

(length "Hello") ;; => 5

(stringp  "a")  ;; => T
(type-of "abc") ;; => (SIMPLE-ARRAY CHARACTER (3))

;; convert to string
(string 'tick) ;; => "TICK"
(string #\c)   ;; => "c"

(equal "a" "a") ;; => T

(string= "x" "y") ;; => NIL
(string= "A" "a") ;; => NIL
;; string NOT equal
(string/= "" "")  ;; => NIL

(string< "a" "b") ;; => 0 means True
(string> "b" "a") ;; => 0 means True
(string> "a" "a") ;; => NIL

(string>= "a" "a") ;; => 1
(string<= "a" "a") ;; => 1

(string-upcase     "hey") ;; => HEY
(string-downcase   "Hey") ;; => hey
(string-capitalize "hEy") ;; => Hey

(string-trim " " " spaces  ")
;; => "spaces"
(string-trim " ,;" " spaces, ;  ")
;; => "spaces"

(subseq "Red green blue" 0 9) ;; => "Red green"
(subseq "Red green blue" 10)  ;; => "blue"

;; split using regex
(cl-ppcre:split "\." "127.0.0.1")
;; => ("127" "0" "0" "1")

(reverse "Hello") ;; => "olleH"

(concatenate 'string "Hello" "World" "!")
;; => "HelloWorld!"
(sort (vector "C" "A" "b" "abc" "Xyz") #'string<))
;; => #("A" "C" "Xyz" "abc" "b")

Format

Format deserves its own special place, because it’s power and super complicated.

Variables & Constants

;; local variables
(let ((x 1) (y 2)) (format nil "~a ~a" x y) )

;; a global (dynamically scoped) variable
;; DEFPARAMETER is a macro which uses SETF and always sets a value
;; by convention, global variables have earmuffs
(defparameter \*number\* 5 "optional docstring")

;; DEFVAR is a macro which uses SETF and doesn't overwrite an already existing value
;; you can use it to define default values, if they don't exist
;; the name comes from "define variable"
(defvar n 1)
(defvar n 2)
(print n) ;; => 1

;; SETF is a macro which uses SETQ internally and is more powerful than SETQ
;; SETF is the most general way of setting values
(defparameter li (list 1 2 3))
(setf (car li) 9)
(car li) ;; => 9

;; SETQ can only define simple values
(setq a 1 b 2 c 3)
(setq 3d '(x y z))
;; SETQ always quotes its first argument, for unquoted, use SET
;; SET is considered deprecated
(set 'name  "Lisp")

;; Constants are defined with DEFCONSTANT
(defconstant server-addr "localhost:8000" "A server host:port")
(documentation 'server-addr 'variable) ;; => "A server host:port"
(constantp server-addr) ;; => true

Functions & Lambdas

;; a function without params
(defun hello-world ()
  "A function that prints & returns Hello."
  (print "Hello World"))

(hello-world) ;; => Hello World

(defun hello (name)
  "Say hello to Name."
  (format t "Hello ~a !~&" name))

(hello "Dude") ;; => Hello Dude !

(defun fib (n)
  "Return the nth Fibonacci number."
  (if (< n 2)
      n
    (+ (fib (- n 1))
       (fib (- n 2)))))

;; call the function like usual
(fib 9) ;; => 34

;; functions can be called programatically
(funcall #'fib 9)
(apply #'fib '(9))

;; #' is a shorthand for (function ...)
(funcall (function +) 1 2)
(apply (function +) '(1 2))

;; simple lambda
(lambda (x) (print x))

Conditionals

(= 1 1) ;; => T
(eql NIL '()) ;; => T

(and T T) ;; => T
(and T nil) ;; => NIL

(or T T) ;; => T
(or T nil) ;; => T

;; IF condition do else
(if T (print "This is True") (print "This is False"))
;; => "This is True"

;; WHEN and UNLESS don't have an ELSE
(when t 'hello)   ;; =>  HELLO
(unless t 'hello) ;; =>  NIL
(when nil 'hello) ;; =>  NIL
(unless nil 'hello) ;;=> HELLO

;; cond macro
(cond ((= a 1) (print 1))
      ((= a 2) (print 2))
      (t 'bigger)) ;; => 1

;; case / switch
(case 1
  ((1) 'is1)
  ((2) 'is2)
  (otherwise 'bigger)) ;; => IS1

;; switch on the type of the value
(typecase 1
  (string "It's a string")
  (integer "It's an int")) ;; => It's an int

Arrays & Vectors

×