Clojure is <3

How to overcome your fear of parens

A presentation by Julien Blanchard

Who am I?

  • Developer at Tigerlily
  • Mainly doing Ruby
  • No Clojure yet but hopefully it will change
  • We're hiring

What will I cover in this talk?

Small introduction to the language

Some features I like about Clojure:

  1. Macros
  2. Multi-methods
  3. Pattern matching

Small introduction to the language

Types


; hello             ; Comment
123456789           ; Long
1234567898765N      ; Arbitrary precision integer
1.234               ; Doubles
1.234M              ; Big decimals
22/7                ; Rational numbers
"chunky bacon"      ; Strings
chunky bacon        ; Symbols
:chunky :bacon      ; Keywords
true false          ; Boolean
nil                 ; Null
#"^chunky\s+bacon$" ; RegExp
\A \b \u2603        ; Characters
					

Collections & Sequences


; Lists
(1 2 3 4 5)
(chunky bacon)
(list 1 2 3)

; Vectors
[1 2 3 4 5]
[chunky bacon]

; Maps
{:chunky "bacon", :foo "bar"}
{:one 1 :two 2}

; Sets
#{:chunky :bacon}
					  

Some branching


(if (> 2 1)               ; test
  "this will be returned" ; true
  "this won't")           ; false

(cond
    (< n 0) "negative"
    (> n 0) "positive"
    :else "zero"))
            

plus and, or, when, if-not...

Functions


(println "Hello Functional programmers!")
; Hello Functional programmers!
; => nil

(println (+ 1 2 3))
; 6
; => nil
            

Functions


(defn hello
  "Print a greeting"
  [first-name last-name]
  (let [full (str first-name " " last-name)]
    (println full)))
            

Parentheses are weird!

But don't let them scare you!


 defn hello
  "Print a greeting"
  [first-name last-name]
  let [full (str first-name " " last-name)]
    println full
            

Some features I like about Clojure

Macros


(unless (> 1 2)
  "this will be returned"
  "this won't'")

(defmacro unless
  [test-exp then else]
  `(if (not ~test-exp)
     ~then
     ~else))
            

Macros


(defmacro assert-equals [expected actual]
    `(when-not (= ~actual ~expected)
        (throw
            (AssertionError.
                (str "Expected " ~expected " but was " ~actual)))))

(assert-equals 6 5)
; => AssertionError Expected 6 but was 5
            
“Lisp is a programmable programming language.”
-- John Foderaro

Multi-methods


(defmulti thoughts-of (fn [person] (:name person)))

(defmethod thoughts-of "Guido" [person]
  (str (person :name) " has one way to do it."))

(defmethod thoughts-of "Rich" [person]
  (str (person :name) " values laziness."))

(defmethod thoughts-of :default [person]
  (str (person :name) " is not a well-known thinker."))
            

Multi-methods


(thoughts-of {:name "Guido"})
; => "Guido has one way to do it."

(thoughts-of {:name "Rich"})
; => "Rich values laziness."

(thoughts-of {:name "Julien"})
; => "Julien is not a well-known thinker."
            

Pattern matching

Destructuring


(def some-numbers [1 2 3 4 5])

(let [[_ _ _ x _] some-numbers] x)
; => 4
            

Destructuring


(defn get-parts
  [ [x y z & others ] ]
    (println "First three are: " x y z)
    (println "Rest is: " others))

(get-parts [ 1 2 3 4 5 ] )
; => First three are:  1 2 3
; => Rest is:  (4 5)
            

Fizz Buzz example


(use '[clojure.core.match :only (match)])

(doseq [n (range 1 101)]
  (println
    (match [(mod n 3) (mod n 5)]
      [0 0] "FizzBuzz"
      [0 _] "Fizz"
      [_ 0] "Buzz"
      :else n)))
            

A great book

Functional Programming for the Object-Oriented Programmer

“This book, written by Brian Marick, is important. Indeed, it may be necessary. We need something to bridge the gap between the huge population of OO programmers, and the growing need for functional programmers. I’ve seen nothing else that fills this need so well.”
-- Robert "Uncle Bob" Martin

Thanks!

I'm @julienXX on Github or Twitter.

Slides available at http://clojure-is-love.herokuapp.com