Skip to content

Instantly share code, notes, and snippets.

@rwilson
Created December 10, 2015 20:59
Show Gist options
  • Save rwilson/b78757e0b3d1378dbcde to your computer and use it in GitHub Desktop.
Save rwilson/b78757e0b3d1378dbcde to your computer and use it in GitHub Desktop.
Clojure Syntax Quick-Start
;;;; Quick Start Syntax
;;
;; Everybody new to clojure without a lot of lisp experience inevitably wants to
;; perform a known operation, without knowing what the clojure fn is to do that.
;; Almost every time you need a fn for some basic operation, clojure already has
;; it defined, but the naming can be unexpected.
;;
;; So, here’s a primer on common operations:
;;;; Functions
;; Defines a function that accepts an arg (called ‘name’) and prints it
;; prn is short for println, str is string concatenation
(fn [name]
(prn (str "hello " name)))
;; However, since we didn’t give the above fn a name, we have no reference to it!
;; So, let’s wrap it in a def, which allows us to define an identity with a value
(def hello-name
"This fn says hello to the caller" ;; cool, a doc string
(fn [name]
(prn (str "hello " name))))
;; Now, we could call:
(hello-name "Ryan") ;; prints “hello Ryan”
(doc hello-name) ;; prints “This fn says hello to the caller”
;; That works, but “def+fn” is so common that there’s a macro shorthand, called “defn”
;; This is the idiomatic way:
(defn hello-name
"This fn says hello to the caller"
[name]
(prn (str "hello " name)))
;; Sometimes we need a fn with shorter syntax. We can also define a fn like this:
#(prn (str "hello " %)) ;; the % refers to the first argument to the fn
;; If we save a reference to that, we can call it, like so:
(def hello-name #(prn (str "hello " %)))
(hello-name "Ryan") ;; prints “hello Ryan”
;; When a shorthand fn accepts >1 argument, they can be referenced positionally:
(def hello-name #(prn (str "hello " %1 " and " %2 )))
(hello-name "Ryan" "Wilson") ;; prints “hello Ryan and Wilson”
;; The shorthand #() syntax is usually reserved for inline fns, like this fn which
;; maps the fn #(inc %) over the collection '(1 2 3), and returns '(2 3 4)
(map #(inc %) '(1 2 3))
;; Or this fn, which maps the fn #(max %1 %2) over the collection '(1 100 10 1000) and
;; returns 1000
(reduce #(max %1 %2) '(1 100 10 1000))
;;;; Maps
;; Under the hood, a clojure map literal is either an array-map or a hash-map,
;; optimized at runtime depending on the size of the map.
(def a-map {:a-key “a value”}) ;; defines a new map (oh, and a semi-colon is a comment)
(:a-key a-map) ;; gets :a-key out of the map, equivalent to (get a-map :a-key)
(:a-key a-map “a default value”) ;; same thing, but with a default value
(assoc a-map :b-key “b value”) ;; associate :b-key -> “b value” in the map (put/set)
(dissoc a-map :b-key) ;; disassociates :b-key, like remove/delete
(def b-map {:b-key “b value”})
(merge a-map b-map) ;; returns {:a-key “a value”, :b-key “b value”}
;;;; Lists
(def a-list (list 1 2 3)) ;; defines a new list, or
(def a-list '(list 1 2 3)) ;; as a list literal, don’t miss the quote!
;; All of these return a new list, but do not modify a-list
(first a-list) ;; returns 1
(second a-list) ;; returns 2
(last a-list) ;; returns 3
(nth a-list 1) ;; returns 2, 0-indexed get element
(next a-list) ;; returns '(2 3)
(take 2 a-list) ;; returns '(1 2)
(drop 1 a-list) ;; '(2 3)
(conj a-list 4) ;; conj(oin)s 4. list addition is at the head, returns '(4 1 2 3)
(cons 4 a-list) ;; creates a new seq, where 4 is the head and a-list is the rest
(concat a-list '(4 5 6)) ;; concatenates the lists, returns '(1 2 3 4 5 6)
;;;; Vectors
(def a-vec (vector 1 2 3)) ;; defines a new vector, or
(def a-vec [1 2 3]) ;; as a vector literal, note there’s no quote like for list!
;; first, second, last, nth, next, take, & drop all work on vectors too
(conj a-vec 4) ;; conj(oin)s 4. vector addition is at the tail, returns [1 2 3 4]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment