Text

A family of many

# Who's a LISP

• Common Lisp
• Scheme
• Clojure
• Racket
• Emacs
• And more...

## What makes LISP special?

• Universally recognizable
• Everything is a list (even LISP)
• S-Expressions
• Truly expressive macros

``(loop (print (eval (read))))``

# LISP: Universally Recognizable

``````; Clojure
(defn factorial [x]
(if (< x 2)
1
(* x (factorial (dec x)))))``````
``````; Common Lisp
(defun fact (n)
(if (< n 2)
1
(* n (fact(- n 1)))))``````
``````; Scheme
(define (factorial n)
(if (<= n 0)
1
(* n (factorial (- n 1)))))``````
``````; Racket
(define (factorial n)
(if (= 0 n)
1
(* n (factorial (- n 1)))))``````
``````(define (factorial n)
(if (<= n 0)
1
(* n (factorial (- n 1)))))``````
``````(defn factorial [x]
(if (< x 2)
1
(* x (factorial (dec x)))))``````
``````(defun fact (n)
(if (< n 2)
1
(* n (fact(- n 1)))))``````
``````(define (factorial n)
(if (= 0 n)
1
(* n (factorial (- n 1)))))``````

Factorial in Common Lisp, Scheme, Racket, and Clojure

# Lists are LISP...

``````; Create an empty list
(def a-list ())
(def a-list (cons 5 nil)) ; nil <--> empty list
(def a-list (cons 1 (cons 2 (cons 3 (cons 4 (cons 5 nil))))))
``````

Lisp is, fundamentally, about lists (LISt Processing)

``````(map inc '(1 2 3 4 5)) ; = (2 3 4 5 6)
(filter even? (map inc '(1 2 3 4 5))) ; = 2 4 6
(reduce + (filter even? (map inc '(1 2 3 4 5)))) ; = 12

; Implementation of Python's range function
(defn range [start finish]
(loop [result nil current (dec finish)]
(if (> current 0)
(recur (cons current result) (dec current))
result)))

; Using range function
(reduce + (filter even? (map inc (range 1 6))))``````

And list processing...

# ...and LISP is Lists

``(println '(println "Hello world!"))``

LISP expressions are lists

Expressions resolve to a value

``(+ 1 1); --> 2``

Expressions can contain expressions

``(+ (* 2 2) (/ 4 2)); --> 6``

Expressions can be evaluated

``````(def x '(reduce * '(1 2 3 4 5))); Our variable contains an expression
(println x); --> (reduce * '(1 2 3 4 5))
(eval x); We can evaluate this expression to retrieve the result (120)``````

# Data is Code, Code is Data

``````; Reads a line from stdin and parses it into an S-Expression

eval:

``````; Evaluates a LISP form
(eval '(println "Hello"))

; Reads, parses, and evaluates a line from stdin

Revisiting the REPL

``````(def basic-repl
(loop []
(recur)))``````

# Code that modifies Code

LISP contains an incredibly powerful macro system

``````(defn greet-person-f [name)
(println (str "Hello " name "!")))``````
``````(defmacro greet-person-m [name]
`(println (str "Hello " ~name "!")))``````

So what's the difference?

``````; Call the function
(greet-person-f "ACM")``````
``````; Call the macro
(greet-person-m "ACM")``````
``````Hello ACM!
nil``````
``````Hello ACM!
nil``````

Wait...what?

# Macros, Macros, Macros

The macroexpand function

``````(macroexpand '(greet-person-f "ACM"))
; --> (greet-person-f "ACM")``````
``````(macroexpand '(greet-person-m "ACM"))
; --> (clojure.core/println (clojure.core/str "Hello " "ACM" "!"))``````

Macros modify the structure of code

# Can't C do this too?

C Macros perform textual substitution:

``#define greetPerson(name) printf( "Hello %s!\n", name )``

LISP macros are expressions evaluated at compile time:

``````(defmacro const
"Evaluate the constant expression expr at compile time."
[expr]
(eval expr))
``````

LISP macros can create functions (or macros):

``````(defmacro defconst [constant-name expr]
"Define a compile time constant"
`(defmacro ~constant-name (const ~expr)))

(defmacro defn-
"Create private function"
[name & decls]
(list* `defn (with-meta name (assoc (meta name) :private true)) decls))``````

# Syntactic Convenience

``(first (.split (.replace (.toUpperCase "a b c d") "A" "X") " "))``

``````(-> "a b c d"
.toUpperCase
(.replace "A" "X")
(.split " ")
first)``````

``````(->> (range)
(map #(* % %))
(filter even?)
(take 10)
(reduce +))``````
``````(macroexpand '(->> (range)
(map #(* % %))
(filter even?)
(take 10)
(reduce +)))``````
``````(reduce +
(take 10
(filter even?
(map (fn* [p1__1211#] (* p1__1211# p1__1211#))
(range)))))
``````

# Fully Featured Macros

Implement new language features (like ADT support):

``````(defn- emit-constructor [adt-name type-name args]
"Emits a type constructor for a particular instance of an ADT"
(let [type-name# (symbol type-name)]
(if (empty? args)
`(defn ~type-name# [~@args]
(with-meta
(struct (create-struct ~@(map keyword args)) ~@args )

"Emits the code to create ADT-like behavior, along with a testing function"
(if (every? list? constructors)
`(do
(defn ~(symbol (str adt-name "?")) [~'x]
~@(for [[type-name args] constructors]
(emit-constructor (str adt-name) (symbol type-name) args)))))``````

# Fully Featured Macros

Implement new language features (like ADT support):

``````(defadt Tree
(Empty  [])
(Leaf   [value])
(Node   [left value right]))

(def other-tree (Node (Node (Leaf 1) 2 (Leaf 3)) 4 (Node (Leaf 5) 6 (Empty))))``````
``````(defmulti string-tree (fn [tree] (-> tree meta :type)))

(defmethod string-tree nil    [value] value)
(defmethod string-tree Empty  [_] "nil")
(defmethod string-tree Leaf   [leaf] (str (leaf :value)))
(defmethod string-tree Node   [node]
(let [left  (string-tree (:left node))
value (string-tree (node :value))
right (string-tree (:right node))]
(format "((%s) %s (%s))" left value right)))

(-> other-tree string-tree read-string flatten pprint) ; (1 2 3 4 5 6 nil)``````

# Questions?

By gizmo385

### LISP - A More Elegant Weapon

An introduction to LISP programming. Emphasizes how LISP differs from other styles of programming, and how those differences make it powerful.

• 804