Skip to content

Instantly share code, notes, and snippets.

@beatngu13
Last active June 12, 2018 10:58
Show Gist options
  • Save beatngu13/af0b4e09d80e9540d27903d5173a6dc1 to your computer and use it in GitHub Desktop.
Save beatngu13/af0b4e09d80e9540d27903d5173a6dc1 to your computer and use it in GitHub Desktop.
Fun with Clojure
;;;;;;;;;;
;;;; Fun with Clojure
;;;;;;;;;;
;; Comments are based on Peter Norvig's recommendations from his tutorial on
;; good Lisp programming style (see
;; http://www.cs.umd.edu/~nau/cmsc421/norvig-lisp-style.pdf on page 41):
;; ; inline comment
;; ;; in-function comment
;; ;;; between-function comment
;; ;;;; section header
;;;;;;;;;;
;;; Map, filter and any
;;;;;;;;;;
(defn my-map [func collection]
(for [value collection] (func value)))
(defn my-filter [predicate collection]
(remove (complement predicate) collection))
(defn my-any [predicate collection]
(let [head (first collection)]
(if (predicate head)
head
(recur predicate (rest collection)))))
(my-map #(* 2 %) [0 1 2 3 4])
;;=> [0 2 4 6 8]
(my-filter even? [0 1 2 3 4])
;;=> [0 2 4]
(my-any odd? [0 1 2 3 4])
;;=> 1
;;;;;;;;;;
;;; Fractions
;;;;;;;;;;
(def my-ratio 2/3)
;;=> 'user/my-ration
(+ my-ratio (/ 1 3))
;;=> 1N
;;;;;;;;;;
;;; Factorial alternatives
;;;;;;;;;;
;; Simple recursion.
(defn factorial1 [n]
(if (zero? n)
1
(* n (factorial1 (dec n)))))
;; Use BigInt.
(defn factorial2 [n]
(if (zero? n)
1N
(*' n (factorial2 (dec n)))))
;; Hide arity by defining a Closure.
(defn factorial3 [n]
(loop [n n
acc 1]
(if (zero? n)
acc
(recur (dec n) (*' n acc)))))
;; Another approach.
(defn factorial4 [n]
(reduce *' (range 1N (inc n))))
;;;;;;;;;;
;;; Functions are values
;;;;;;;;;;
(defn sum [collection]
(reduce + collection))
(defn avg [collection]
(/ (sum collection) (count collection)))
(defn stats
"Takes a collection of numbers and returns a vector with their
sum, the number of elements as well as the average value."
[numbers]
(map #(% numbers) [sum count avg]))
(stats [1 2 3])
;;=> [6 3 2]
;;;;;;;;;;
;;; Magic with map
;;;;;;;;;;
(reduce (fn [new-map [key val]]
(if (> val 4)
(assoc new-map key val)
new-map))
{}
{:human 4.1
:critter 3.9})
;;=> {:human 4.1}
;;;;;;;;;;
;;; Sequences and collections
;;;;;;;;;;
;; seq (first, rest, cons).
(cons 1 '(2 3))
;;=> (1 2 3)
(cons 1 [2 3])
;;=> (1 2 3)
;; coll (into, conj).
(conj '(2 3) 1)
;;=> (1 2 3)
(conj [2 3] 1)
;;=> [2 3 1]
;; Rest parameters (e.g. conj) vs. seqable data structures (e.g. into).
(max 1 2 3)
;;=> 3
(max [1 2 3])
;;=> [1 2 3]
;; "Explode" elements to pass them as separate values.
(apply max [1 2 3])
;;=> 3
;; Vice versa.
(defn logger [lvl msg]
(let [date (new java.util.Date)]
(condp = lvl
:warning (str "WARNING [" date "]: " msg)
:error (str "ERROR [" date "]: " msg))))
(def warn (partial logger :warning))
;;;;;;;;;;
;;; Lazy sequences
;;;;;;;;;;
(def lazy-fib
(lazy-cat [0 1] (map + lazy-fib (rest lazy-fib))))
(defn fib [n]
((vec (take (inc n) lazy-fib)) n))
(take 10 fibonnaci)
;;=> (0 1 1 2 3 5 8 13 21 34)
;;;;;;;;;;
;;; The power of macros
;;;;;;;;;;
(defmacro foreach [[sym coll] & body]
`(loop [coll# ~coll]
(when-let [[~sym & xs#] (seq coll#)]
~@body
(recur xs#))))
(foreach [x [1 2 3]] (println x))
;;=> 1
;;=> 2
;;=> 3
;;=> nil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment