clojure basics
TRANSCRIPT
![Page 2: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/2.jpg)
Clojure 1.5 was released on March 1st, 2013.
Read this to see changes:https://github.com/clojure/clojure/blob/master/changes.md
My examples use 1.4.0.
Tuesday, March 19, 13
![Page 3: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/3.jpg)
“Startups tend to be an all or nothing proposition. You either get rich, or you get nothing. In a startup, if you bet on the wrong technology, your competitors will crush you.”
Paul Graham
Tuesday, March 19, 13
![Page 4: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/4.jpg)
“When you choose technology, you have to ignore what other people are doing, and consider only what will work the best.”
Paul Graham
Tuesday, March 19, 13
![Page 5: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/5.jpg)
“In a big company, you can do what all the other big companies are doing. But a startup can't do what all the other startups do. I don't think a lot of people realize this, even in startups.”
Paul Graham
Tuesday, March 19, 13
![Page 6: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/6.jpg)
“So if you're running a startup, you had better be doing something odd. If not, you're in trouble.”
Paul Graham
Tuesday, March 19, 13
![Page 7: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/7.jpg)
“Lisp is so great not because of some magic quality visible only to devotees, but because it is simply the most powerful language available. And the reason everyone doesn't use it is that programming languages are not merely technologies, but habits of mind as well, and nothing changes slower.”
Paul Graham
Tuesday, March 19, 13
![Page 8: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/8.jpg)
“I'll begin with a shockingly controversial statement: programming languages vary in power.”
Paul Graham
Tuesday, March 19, 13
![Page 9: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/9.jpg)
http://pragprog.com/book/shcloj2/programming-clojure http://clojure.org
Tuesday, March 19, 13
![Page 10: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/10.jpg)
Tuesday, March 19, 13
![Page 11: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/11.jpg)
Rich Hickey is a genius. And, I’m just here to piss you off.
Clojure Concurrencyhttp://blip.tv/clojure/clojure-concurrency-819147
22:00 - 23:18
Simple Made Easyhttp://www.infoq.com/presentations/Simple-Made-Easy
15:30 - 17:15
Tuesday, March 19, 13
![Page 12: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/12.jpg)
Why you should take a look...
functional langs can more easily use multiple cores
purely functional is awkward when dealing with state
Clojure has refs, agents, atoms, dynamic binding
dynamic typing
Java invocation (not functional)
refs (STM)
JVM, calling Java is idiomatic
Tuesday, March 19, 13
![Page 13: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/13.jpg)
CLOJURE BASICS
Why is Clojure so cool necessary?
Basic Setup x2 or 3
Language Basics
Working with State (or without it)
Working with government forms Java
Macros
Webby Stuff
Testing
Clojure + Processing + Kinect/OpenNI
Tuesday, March 19, 13
![Page 14: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/14.jpg)
Why is Clojure necessary?
Tuesday, March 19, 13
![Page 15: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/15.jpg)
Multi-Core Future
Tuesday, March 19, 13
![Page 16: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/16.jpg)
Why use the JVM?
The JVM is advanced technology.
Java libraries... lots of them.
Widely deployed
Tuesday, March 19, 13
![Page 17: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/17.jpg)
Using the JVMFor example: https://github.com/mmcgrana/clj-redis
(require '[clj-redis.client :as redis])
(def db (redis/init))
(redis/ping db)=> "PONG"
(redis/set db "foo" "BAR")=> "OK"
(redis/get db "foo")=> "BAR"
Tuesday, March 19, 13
![Page 18: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/18.jpg)
JVMFor example: https://github.com/mmcgrana/clj-redis
(ns clj-redis.client (:import java.net.URI) (:import (redis.clients.jedis Jedis JedisPool JedisPoolConfig JedisPubSub)) (:require [clojure.string :as str]) (:refer-clojure :exclude [get set keys type]))
(def ^{:private true} local-url "redis://127.0.0.1:6379")
(defn init ([] (init {})) ([{:keys [url timeout test-on-borrow] :as opts}] (let [uri (URI. (or url local-url)) tout (or timeout 2000) host (.getHost uri) port (if (pos? (.getPort uri)) (.getPort uri) 6379) uinfo (.getUserInfo uri) pass (and uinfo (last (str/split uinfo #":"))) config (JedisPoolConfig.)] (when test-on-borrow (.setTestOnBorrow config test-on-borrow)) (JedisPool. config host port tout pass))) ([k1 v1 & {:as opts}] (init (assoc opts k1 v1))))
Tuesday, March 19, 13
![Page 19: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/19.jpg)
JVMFor example: https://github.com/mmcgrana/clj-redis
(defn lease [^JedisPool p f] (let [j (.getResource p)] (try (f j) (finally (.returnResource p j)))))
(defn ping [p] (lease p (fn [^Jedis j] (.ping j))))
(defn get [p ^String k] (lease p (fn [^Jedis j] (.get j k))))
(defn set [p ^String k ^String v] (lease p (fn [^Jedis j] (.set j k v))))
Tuesday, March 19, 13
![Page 20: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/20.jpg)
Why is Clojure a secret weapon?
http://www.paulgraham.com/avg.html
Tuesday, March 19, 13
![Page 21: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/21.jpg)
Why is Clojure so cool?
Homoiconic
Modern LISP
Functional (but not purely functional)
Tuesday, March 19, 13
![Page 22: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/22.jpg)
Homoiconic
Lisp code is just lisp data
Revenge of the Nerds - Paul Graham
Macros == black magic
Reprogramming the language with the language
Tuesday, March 19, 13
![Page 23: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/23.jpg)
Modern
Fewer parentheses
Sequences
Reader macros for data structures
regex, map, set, vector, metadata
First-class data structures: [], {}, ‘()
Less Lipsy than other Lisps (ex: fns use [ ])
Commas are whitespace
Tuesday, March 19, 13
![Page 24: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/24.jpg)
List Comprehension
user> (take 40 (for [x (range) :when (and (> (* 2 x) 99) (= 0 (mod x 3)))] (* 2 x)))(102 108 114 120 126 132 138 144 150 156162 168 174 180 186 192 198 204 210 216222 228 234 240 246 252 258 264 270 276282 288 294 300 306 312 318 324 330 336)
Tuesday, March 19, 13
![Page 25: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/25.jpg)
Functional
Functions are first-class
Data is immutable
Functions are NOT pure
Tuesday, March 19, 13
![Page 26: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/26.jpg)
Why Functional?
Simple
Thread-safe
Parallelizable
Generic
Tuesday, March 19, 13
![Page 27: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/27.jpg)
Clojure’s approach to Functional Programming
Not purely functional
Has system for working with refs, agents, atoms, and dynamic binding
Dynamic typing
Java invocation is NOT functional
Tuesday, March 19, 13
![Page 28: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/28.jpg)
“Mutable objects are the new spaghetti code.”- Rich Hickey
Tuesday, March 19, 13
![Page 29: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/29.jpg)
Concurrency is difficult
Tuesday, March 19, 13
![Page 30: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/30.jpg)
You can’t stop the world
http://clojure.org/concurrent_programming
http://blip.tv/clojure/clojure-concurrency-819147
http://www.infoq.com/presentations/Value-Values
Tuesday, March 19, 13
![Page 31: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/31.jpg)
Concurrency is difficult
Persistent data structures
Programming with values
Immutable by default
Syntax for state:
Refs (STM), Agents, Atoms, Dynamic Vars
We’ll a bit about state later.
Tuesday, March 19, 13
![Page 32: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/32.jpg)
Enough chit chat.
Tuesday, March 19, 13
![Page 33: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/33.jpg)
Let’s get started
there are a few options
Emacs, Leiningen, nrepl
Emacs Live
LightTable
Tuesday, March 19, 13
![Page 34: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/34.jpg)
Leiningen
Clojure automation...https://github.com/technomancy/leiningen
1) Download the script:
https://raw.github.com/technomancy/leiningen/stable/bin/lein
2) Place it on your $PATH. (I like to use ~/bin)
3) Set it to be executable. (chmod 755 ~/bin/lein)
Start a new project:$ lein new <project name>$ lein repl
Tuesday, March 19, 13
![Page 35: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/35.jpg)
Emacs
Get version >= 24.X
Pick one (or more):
1) http://emacsformacosx.com
2) $ brew install emacs
3) https://github.com/overtone/emacs-live
Tuesday, March 19, 13
![Page 36: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/36.jpg)
Emacs https://gist.github.com/mudphone/4698169= install lein 2- Do this: https://github.com/technomancy/leiningen- download lein script, it will boot strap itself- install on path, rename to lein, chmod 755- run lein --version Leiningen 2.0.0 on Java 1.6.0_37 Java HotSpot(TM) 64-Bit Server VM = Emacs >= 24- Download latest version: http://emacsformacosx.com, if you want the GUI version- Or, for CLI, use homebrew- Or, do both = Emacs Starter Kit- look at my init.el- install latest: https://github.com/technomancy/emacs-starter-kit- install clojure-mode package-install <ret> clojure-mode <ret>- install nrepl" package-install <ret> nrepl <ret> = nrepl (already installed)- docs here: https://github.com/kingtim/nrepl.el- at a minimum, check out the keybindings = nrepl auto-complete- https://github.com/purcell/ac-nrepl (popup docs keybinding didn't work for me, so I'm not using it right now) = REFS:- this isn't required reading, but it works: http://www.kedrovsky.com/blog/clojure-emacs-nrepl-and-leiningen
Tuesday, March 19, 13
![Page 37: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/37.jpg)
Emacs
nREPL
M-x nrepl-jack-in
C-c M-n (to switch repl to this ns)
C-x C-c (eval buffer in repl)
M-C-x (eval form under point in repl)
C-c C-z (switch to repl buffer)
Tuesday, March 19, 13
![Page 38: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/38.jpg)
Clojure Basics
Tuesday, March 19, 13
![Page 39: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/39.jpg)
Getting Started
Symbols
Vars
Namespaces
use == require + refer
Help w/ doc, find-doc, source
Tuesday, March 19, 13
![Page 40: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/40.jpg)
Forms
Prefix notation
false and nil evaluate to false
maps are functions of keys, and keys are functions of maps
defrecord
Tuesday, March 19, 13
![Page 41: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/41.jpg)
defrecord
user> (defrecord Person [fname lname age favorites])user.Personuser> (defrecord Favorites [movie band])user.Favoritesuser> (def me (Person. "Kyle" "Oba" 37 (Favorites. "Lost in Translation" "Pantera")))#'user/meuser> (:fname me)"Kyle"
user> (-> me :favorites :movie)"Lost in Translation"
user> (assoc me :fname "That guy")#user.Person{:fname "That guy", :lname "Oba", :age 37, :favorites #user.Favorites{:movie "Lost in Translation", :band "Pantera"}}
user> (update-in me [:favorites :band] #(str "ZZ" % "ZZ"))#user.Person{:fname "Kyle", :lname "Oba", :age 37, :favorites #user.Favorites{:movie "Lost in Translation", :band "ZZPanteraZZ"}}
Tuesday, March 19, 13
![Page 42: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/42.jpg)
State http://clojure.org/state
http://clojure.org/concurrent_programming
http://clojure.org/vars
http://clojure.org/atoms
http://clojure.org/agents
http://clojure.org/refs
Tuesday, March 19, 13
![Page 43: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/43.jpg)
Imperative programming
single-threaded premise
world is stopped
requires mutexes and locks
difficult to get right / extremely complicated
Tuesday, March 19, 13
![Page 44: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/44.jpg)
Identity and Value
identity
value
name
Kyle
fav foods
{cheese donutsbacon}
today
March18th 2013
Tuesday, March 19, 13
![Page 45: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/45.jpg)
Typical OO
has imperative programming baked into it
identities are conflated with values
not necessarily, but usually, due to the language
Tuesday, March 19, 13
![Page 46: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/46.jpg)
Clojure’s approach
separates state from identity
move away from state as “the content of this memory block”
toward “the value currently associated with this identity”
identity is in different states at different times
but, the state at a point in time never changes value
Tuesday, March 19, 13
![Page 47: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/47.jpg)
Clojure’s approach
vars - root binding, refers to mutable storage location
vars w/ dynamic binding - per-thread binding
atoms
agents, asynchronous change via a function and values
refs, coordinate change with STM: software transactional memory
Tuesday, March 19, 13
![Page 48: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/48.jpg)
Actor Model (not Clojure)
distributed
more complex
see Erlang
Tuesday, March 19, 13
![Page 49: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/49.jpg)
Working with State
atoms
refs
dynamic binding
acting at a distance / aspect oriented programming
loss of purity
memoize example
Tuesday, March 19, 13
![Page 50: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/50.jpg)
Working with State
Tuesday, March 19, 13
![Page 51: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/51.jpg)
vars
user> (def x 1)#'user/x
user> x1
user> (def y 1)#'user/y
user> (+ x y)2
allow reference to mutable storage locations
Tuesday, March 19, 13
![Page 52: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/52.jpg)
dynamic binding
user> (def ^:dynamic x 1)#'user/x
user> (def ^:dynamic y 1)#'user/y
user> (+ x y)2
user> (binding [x 2 y 3] (+ x y))5
user> (+ x y)2
Tuesday, March 19, 13
![Page 53: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/53.jpg)
Changing State async synchronous
coordinated
independent atom
ref
agent
Tuesday, March 19, 13
![Page 54: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/54.jpg)
atoms
user> (def z (atom 5))#'user/z
user> z#<Atom@f2882ad: 5>
user> @z5
user> (swap! z inc)6
user> @z6
user> (swap! z (constantly 10))10
user> @z10
shared, synchronous, independent state
Tuesday, March 19, 13
![Page 55: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/55.jpg)
agents independent, asynchronous change
user> (def a (agent 1))#'user/a
user> a#<Agent@474d75ae: 1>
user> (send a inc)#<Agent@474d75ae: 2>
user> a#<Agent@474d75ae: 2>
user> @a2
user> (send a #(do (Thread/sleep 5000) (+ % 1)))#<Agent@474d75ae: 2>
user> @a2
user> @a3
Tuesday, March 19, 13
![Page 56: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/56.jpg)
refs (transactional references)shared use of mutable storage via STM
user> (def r (ref [1 2 3]))#'user/r
user> r#<Ref@369ca84f: [1 2 3]>
user> @r[1 2 3]
(dosync (alter r #(conj % 4)))[1 2 3 4]
user> @r[1 2 3 4]
user> (dosync (alter r (partial cons 0)))(0 1 2 3 4)
user> @r(0 1 2 3 4)
Tuesday, March 19, 13
![Page 57: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/57.jpg)
Java Interop
Tuesday, March 19, 13
![Page 58: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/58.jpg)
Working with Java
Calling Java
Java interop
Java collections
Tuesday, March 19, 13
![Page 59: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/59.jpg)
Java: Examples
user> (System/getProperty "java.vm.version")"20.14-b01-447"
user> (.toUpperCase "fred")"FRED"
user> (.getName String)"java.lang.String"
user> Math/PI3.141592653589793
Tuesday, March 19, 13
![Page 60: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/60.jpg)
Java: import and .
user> (import '[java.util Random])java.util.Random
user> (def r (Random.))#'user/r
user> (.nextInt r)458809484
user> (.nextInt r 100)42
Tuesday, March 19, 13
![Page 61: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/61.jpg)
Java: doto
user> (doto (new java.util.HashMap) (.put "a" 1) (.put "b" 2))#<HashMap {b=2, a=1}>
Tuesday, March 19, 13
![Page 62: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/62.jpg)
Java: set!
user> (def p (java.awt.Point.))#'user/p
user> (.x p)0
user> (set! (. p x) 5)5
user> p#<Point java.awt.Point[x=5,y=0]>
Tuesday, March 19, 13
![Page 63: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/63.jpg)
Macros
Tuesday, March 19, 13
![Page 64: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/64.jpg)
What’s a Macro?
#!/usr/bin/env ruby -wsay_hello = "puts \"hello\""
ruby_cmd = (0..9).map do |n| say_helloend
puts "ruby -e '#{ruby_cmd.join(";")}'"
$ ruby ruby_macro.rb | shhellohellohellohellohellohellohellohellohellohello
What if we could do this, while staying in the language?
Tuesday, March 19, 13
![Page 65: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/65.jpg)
Ruby-like “unless” implementation as a function...
This won’t work, because arguments are evaluated.
(defn unless [expr form] (if expr nil form))
user> (unless (= 1 1) (println "hi"))hinil
Tuesday, March 19, 13
![Page 66: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/66.jpg)
Arguments are evaluated first
(defn unless [expr form] (println "Doing unless...") (if expr nil form))
user> (unless (= 1 1) (println "hi"))hiDoing unless...nil
Tuesday, March 19, 13
![Page 67: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/67.jpg)
What we want
(unless expr form) -> (if expr nil form)
Tuesday, March 19, 13
![Page 68: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/68.jpg)
What we want
(defmacro unless [expr form] (list 'if expr nil form))
user> (unless true (println "yep"))nil
user> (unless false (println "yep"))yepnil
Tuesday, March 19, 13
![Page 69: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/69.jpg)
macroexpand-1
user> (macroexpand-1 '(when-not true (println "hi")))(if true nil (do (println "hi")))
user> (source when-not)(defmacro when-not "Evaluates test. If logical false, evaluates body in an implicit do." {:added "1.0"} [test & body] (list 'if test nil (cons 'do body)))nil
Tuesday, March 19, 13
![Page 70: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/70.jpg)
WAT
reader
compile
macros
text
data structures
bytecode
macrosevaluation
Tuesday, March 19, 13
![Page 71: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/71.jpg)
macroexpand
user> (.. System (getProperties) (get "os.name"))"Mac OS X"
user> (macroexpand-1 '(.. System (getProperties) (get "os.name")))(.. (. System (getProperties)) (get "os.name"))
user> (macroexpand '(.. System (getProperties) (get "os.name")))(. (. System (getProperties)) (get "os.name"))
Tuesday, March 19, 13
![Page 72: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/72.jpg)
Java Interop Bonus
user> (source ..)(defmacro .. "form => fieldName-symbol or (instanceMethodName-symbol args*)
Expands into a member access (.) of the first member on the first argument, followed by the next member on the result, etc. For instance:
(.. System (getProperties) (get \"os.name\"))
expands to:
(. (. System (getProperties)) (get \"os.name\"))
but is easier to write, read, and understand." {:added "1.0"} ([x form] `(. ~x ~form)) ([x form & more] `(.. (. ~x ~form) ~@more)))nil
Tuesday, March 19, 13
![Page 73: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/73.jpg)
One more macro...
user> (source and)(defmacro and "Evaluates exprs one at a time, from left to right. If a form returns logical false (nil or false), and returns that value and doesn't evaluate any of the other expressions, otherwise it returns the value of the last expr. (and) returns true." {:added "1.0"} ([] true) ([x] x) ([x & next] `(let [and# ~x] (if and# (and ~@next) and#))))nil
Tuesday, March 19, 13
![Page 74: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/74.jpg)
“Webby Stuff”
Tuesday, March 19, 13
![Page 75: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/75.jpg)
Areas of Interest:
ClojureScript to any old websitehttp://blip.tv/clojure/rich-hickey-unveils-clojurescript-5399498
ClojureScript + Three.js, to get at the WebGL bits
ClojureScript embedded in game systems
ClojureScript CLI
Pedestal: http://pedestal.io/documentation/hello-world-service/
It runs on Node.js.
Tuesday, March 19, 13
![Page 76: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/76.jpg)
ClojureScript$ lein cljsbuild onceCompiling ClojureScript.Compiling "resources/public/hello.js" from "src/cljs"...Successfully compiled "resources/public/hello.js" in 8.542318 seconds.
$ tree.├── README.md├── doc│ └── intro.md├── docroot│ └── index.html├── project.clj├── resources│ └── public│ ├── hello.js│ └── index.html├── src│ ├── clj│ │ └── hello_world│ │ └── core.clj│ └── cljs│ └── hello.cljs└── test └── hello_world └── core_test.clj
10 directories, 9 files
Tuesday, March 19, 13
![Page 77: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/77.jpg)
Pedestal$ tree.├── README.md├── config│ └── logback.xml├── dev│ ├── dev.clj│ └── user.clj├── logs│ └── helloworld-2013-03-18.0.log├── project.clj├── src│ └── helloworld│ ├── server.clj│ └── service.clj├── target│ ├── classes│ └── stale│ └── extract-native.dependencies└── test └── helloworld └── service_test.clj
10 directories, 10 files
$ lein replnREPL server started on port 63132...helloworld.server=> (use 'dev)nilhelloworld.server=> (start)nilhelloworld.server=> (stop)nilhelloworld.server=> Bye for now!
http://pedestal.io/documentation/hello-world-service/
Tuesday, March 19, 13
![Page 78: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/78.jpg)
Pedestalhttp://pedestal.io/documentation/application-introduction/
(defn count-model [old-state message] (condp = (msg/type message) msg/init (:value message) :inc (inc old-state)))
(defmulti render (fn [& args] (first args)))
(defmethod render :default [_] nil)
(defmethod render :value [_ _ old-value new-value] (dom/destroy-children! (dom/by-id "content")) (dom/append! (dom/by-id "content") (str "<h1>" new-value " Hello Worlds</h1>")))
(defn render-fn [deltas input-queue] (doseq [d deltas] (apply render d)))
(def count-app {:models {:count {:init 0 :fn count-model}}})
(defn receive-input [input-queue] (p/put-message input-queue {msg/topic :count msg/type :inc}) (.setTimeout js/window #(receive-input input-queue) 3000))
(defn ^:export main [] (let [app (app/build count-app)] (render/consume-app-model app render-fn) (receive-input (:input app)) (app/begin app)))
(ns hello-world(:require [io.pedestal.app.protocols :as p] [io.pedestal.app :as app] [io.pedestal.app.messages :as msg] [io.pedestal.app.render :as render] [domina :as dom]))
Tuesday, March 19, 13
![Page 79: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/79.jpg)
Pedestalhttp://pedestal.io/documentation/application-introduction/
(ns hello-world (:require [io.pedestal.app.protocols :as p] [io.pedestal.app :as app] [io.pedestal.app.messages :as msg] [io.pedestal.app.render :as render] [io.pedestal.app.render.push :as push] [domina :as dom]))
(defn count-model [old-state message] (condp = (msg/type message) msg/init (:value message) :inc (inc old-state)))
(defn render-value [renderer [_ _ old-value new-value] input-queue] (dom/destroy-children! (dom/by-id "content")) (dom/append! (dom/by-id "content") (str "<h1>" new-value " Hello Worlds</h1>")))
(def count-app {:models {:count {:init 0 :fn count-model}}})
(defn receive-input [input-queue] (p/put-message input-queue {msg/topic :count msg/type :inc}) (.setTimeout js/window #(receive-input input-queue) 3000))
(defn ^:export main [] (let [app (app/build count-app) render-fn (push/renderer "content" [[:value [:*] render-value]])] (render/consume-app-model app render-fn) (receive-input (:input app)) (app/begin app)))
Tuesday, March 19, 13
![Page 80: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/80.jpg)
Testing
Tuesday, March 19, 13
![Page 81: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/81.jpg)
(ns oudl.core-test (:use clojure.test oudl.core))
(deftest a-test (testing "FIXME, I fail." (is (= 0 1))))
user> (require '[clojure.test :as test])nil
user> (test/run-all-tests #"oudl.*-test")
Testing oudl.core-test
FAIL in (a-test) (core_test.clj:7)FIXME, I fail.expected: (= 0 1) actual: (not (= 0 1))
Ran 1 tests containing 1 assertions.1 failures, 0 errors.{:type :summary, :pass 0, :test 1, :error 0, :fail 1}
Free!
Tuesday, March 19, 13
![Page 82: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/82.jpg)
(require ‘[clojure.test :as test])
user> (doc test/run-all-tests)-------------------------clojure.test/run-all-tests([] [re]) Runs all tests in all namespaces; prints results. Optional argument is a regular expression; only namespaces with names matching the regular expression (with re-matches) will be tested.nil
user> (doc test/run-tests)-------------------------clojure.test/run-tests([] [& namespaces]) Runs all tests in the given namespaces; prints results. Defaults to current namespace if none given. Returns a map summarizing test results.nil
Tuesday, March 19, 13
![Page 83: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/83.jpg)
Things I Like
Tuesday, March 19, 13
![Page 84: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/84.jpg)
Some things
Clojure + Processing = Quil
Clojure + Kinect/OpenNI = Bifocals
LightTable
Tuesday, March 19, 13
![Page 85: Clojure basics](https://reader034.vdocuments.net/reader034/viewer/2022052216/554a0760b4c9055b7a8b5687/html5/thumbnails/85.jpg)
Tuesday, March 19, 13