getting' clojure - '(parentheses are just hugs for your code)
DESCRIPTION
http://gtrak.github.io/bohconf.clojureTRANSCRIPT
![Page 1: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/1.jpg)
'GETTING' CLOJURE'GETTING' CLOJURE'(PARENTHESES ARE JUST HUGS FOR YOUR CODE)'(PARENTHESES ARE JUST HUGS FOR YOUR CODE)
Created by / Jason Lewis Gary Trakhman
![Page 2: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/2.jpg)
Javascript
function() return 5;
FUNCTIONSFUNCTIONS
![Page 3: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/3.jpg)
Put some parens around it, kill the braces
(function() return 5; )
![Page 4: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/4.jpg)
Change 'function' to 'fn', makes args into a vector
(fn [] return 5; )
![Page 5: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/5.jpg)
Kill the 'return', last thing's always returned.
Welcome to Clojure.
(fn [] 5)
![Page 6: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/6.jpg)
Move the left parenthesis over a bit more...
Done.
someFunction(arg1, arg2, arg3);
(someFunction arg1 arg2 arg3)
CALLING STUFFCALLING STUFF
![Page 7: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/7.jpg)
THIS ISN'T AN ACCIDENTTHIS ISN'T AN ACCIDENTJavascript is 'Lisp in C's Clothing'Says Crockford: http://www.crockford.com/javascript/javascript.html
![Page 8: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/8.jpg)
PUT ANOTHER WAY...PUT ANOTHER WAY...Q: Why do you think we've gotten so much mileage out ofjavascript?A: Lisp is very powerful, and it will never die
![Page 9: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/9.jpg)
Should look familiar
Don't freak out
DON'T FREAK OUT
:key1 5, :key2 nil
[1 2 3 4 "five"]
[1 [2] #3 4 4 (constantly 5)]
=> (range 10)(0 1 2 3 4 5 6 7 8 9)
=> (take 11 (range))(0 1 2 3 4 5 6 7 8 9 10)
=> (last (range)) ;;Hope you don't mind waiting a long time.
DATADATA
![Page 10: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/10.jpg)
Evals to...
;; semicolons are comments, commas are ignored,;; check out this weird hashmap:akeyword 5,
"a string key" "a string value",
["a" :vector "acting" :as [:a :compound] "key"]
(fn [] "a noarg functionthat returns this multiline string,the function itself is the value"),
+ '(functions can be keys too, and whenyou quote symbols, you justhave symbols, not what they represent)
:akeyword 5, "a string key" "a string value",["a" :vector "acting" :as [:a :compound] "key"]#<user$eval331$fn__332 user$eval331$fn__332@a585ef>,#<core$_PLUS_ clojure.core$_PLUS_@20a12d8f>(functions can be keys too and when you quote symbols you just have symbols not what they represent)
EVERYTHING IS DATAEVERYTHING IS DATA
![Page 11: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/11.jpg)
ANYTHING CAN BE A KEY, BECAUSEANYTHING CAN BE A KEY, BECAUSE1. Every object is also a 'value'2. Values have true equality3. Values Never Change (Immutability)4. Without immutability, objects are just buckets in memory
...have you ever trusted a bucket with no values?
![Page 12: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/12.jpg)
Q: Why is this big news?
A: I can write code and rest assured that other parts of myprogram can't change the data that I'm working on.
Q: But I thought every program is simply a short-lived httprequest handler that talks to a database? We just throw theprogram state out after every request!
A: Well, that's one way to do it.
![Page 13: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/13.jpg)
http://www.ibm.com/developerworks/library/wa-aj-multitier2/
![Page 14: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/14.jpg)
NODE.JS...NODE.JS...http://www.andrerodrigues.me/isel-
workshop/intro.html#/24
![Page 15: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/15.jpg)
NODE.JS... IS NOTHING NEWNODE.JS... IS NOTHING NEWWe can write our own loopsNode.js assumes threaded programming is hard, andthrows out the baby with the bath-waterThreaded programming is hard without real 'Data' or'Values'Composition of any sort is simpler with data
![Page 16: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/16.jpg)
APPROXIMATING NODE.JSAPPROXIMATING NODE.JS'Agents' are asynchronous queues, sharing threadpools todo work, storing the last value returned.
(defn inclast [val] (conj val (inc (last val))))
;; We make a sequence of 10 inclast tasks,;; then followup with a 'println' task(def tasks (concat (repeat 10 inclast) [(fn [val] (println val) val)]))
![Page 17: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/17.jpg)
;; starts off with a value of [0](let [a (agent [0])] (doseq [t tasks] (send a t)))
;; prints: [0 1 2 3 4 5 6 7 8 9 10]
Agents are not values, they are mutable references withasynchronous semanticsClojure has other mutable references types, acting as'containers' for values, for various use cases.Nothing prevents you from making your own.
![Page 18: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/18.jpg)
(let [f (future (doabunchofstuff))] ;; in another thread (dostuffinthisthread) ;; return the value in f, blocking if it's not finished (deref f))
MORE!MORE!
Basically,Clojure promotes your ability to do whatever you want, bysimplifying things to their bare essence.
![Page 19: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/19.jpg)
WHAT WE REALLY WANTWHAT WE REALLY WANTTools that let us
1. Compose Systems2. Change our minds3. Re-use components in different contexts, processes,
servers, etc..
Data/Values give us the ability to decouple things easily
![Page 20: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/20.jpg)
'(code is data)
BRAINSPLODEBRAINSPLODE
![Page 21: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/21.jpg)
Read-Eval-Print-Loop
(class (readstring "(+ 1 2)"));; clojure.lang.PersistentList
(map class (readstring "(+ 1 2)"));; (clojure.lang.Symbol java.lang.Long java.lang.Long)
R-E-P-LR-E-P-L1. Read: (read-string "(+ 1 2)") => '(+ 1 2)2. Eval: (eval '(+ 1 2)) => 33. What if there's something in the middle?
![Page 22: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/22.jpg)
This is only the beginning
(defn onlyeven! [val] (if (and (integer? val) (odd? val)) (inc val) val))
(map onlyeven! (readstring "(+ 1 2)"));; '(+ 2 2)
(eval (map onlyeven! (readstring "(+ 1 2)")));; 4
![Page 23: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/23.jpg)
Everybody likes chaining, right?
How is this implemented? Is this reusable?
$("#p1").css("color","red").slideUp(2000).slideDown(2000);
![Page 24: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/24.jpg)
What if, as a library author, you could just not write that fluentinterface code at all?
(use 'clojure.string)
;; These are equivalent
(map trim (split (uppercase "hola, world") #","));; ("HOLA" "WORLD")
(> "hola, world" uppercase (split #",") (>> (map trim)));; ("HOLA" "WORLD")
![Page 25: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/25.jpg)
Really useful when you're doing a lot of collection operations,filtering, etc.
(>> (range) (filter even?) (map (partial * 2)) (take 10) (into []));; [0 4 8 12 16 20 24 28 32 36]
;; versus(into [] (take 10 (map (partial * 2) (filter even? (range)))))
1. I find the flat one easier to think about.2. Semantically equivalent.3. No burden on implementing code. Functions don't care
about how they're used.
Giving the user choices is more effective with more powerfullanguages. Leads to simple, composable libraries.
![Page 26: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/26.jpg)
Let's look at a real one.
(defmacro lazyseq "Takes a body of expressions that returns an ISeq or nil, and yields a Seqable object that will invoke the body only the first time seq is called, and will cache the result and return it on all subsequent seq calls. See also realized?" :added "1.0" [& body] (list 'new 'clojure.lang.LazySeq (list* ':once true fn* [] body)))
;; simply returns a list, allocates a Java object (LazySeq) and wraps;; your expressions in a function
(macroexpand1 '(lazyseq ANYTHING1 ANYTHING2));; '(new clojure.lang.LazySeq (fn* [] ANYTHING1 ANYTHING2))
MACROSMACROS
![Page 27: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/27.jpg)
Let's create an infinite sequence representing a square-wave --__--__--__--__
No mutable variables
(defn squarewave "t is the period for a halfcycle" [t] (letfn [(osc [curvalue sofar] (let [sofar (mod sofar t) nextval (if (zero? sofar) ( curvalue) curvalue)] (cons nextval (lazyseq (osc nextval (inc sofar))))))] (osc 1 0)))
(take 10 (squarewave 3));; (1 1 1 1 1 1 1 1 1 1)
![Page 28: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/28.jpg)
CALL TO ACTIONCALL TO ACTION1. Learn Clojure2. Build cool things3. Screencasts!
(You ruby guys really know how to make good screencasts)
![Page 29: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/29.jpg)
DEMO TIMEDEMO TIMECLOJURE ON THE WEBCLOJURE ON THE WEB
Now clone this:
https://github.com/canweriotnow/bohjure
![Page 30: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/30.jpg)
RESOURCESRESOURCESClojure: http://clojure.org
Fun Exercises: http://www.4clojure.comCheatsheets: http://clojure.org/cheatsheet
Building: https://github.com/technomancy/leiningenInsight: http://www.youtube.com/user/ClojureTV
Community docs: http://clojuredocs.orgBlogs: http://planet.clojure.in
Light Table: http://www.lighttable.comthis doc: http://gtrak.github.io/bohconf.clojure
![Page 31: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/31.jpg)
MORE DEMO TIMEMORE DEMO TIME
![Page 32: Getting' Clojure - '(parentheses are just hugs for your code)](https://reader035.vdocuments.us/reader035/viewer/2022081403/5560cb2cd8b42a08088b49d4/html5/thumbnails/32.jpg)
THANKS FOR COMING!THANKS FOR COMING!WE ARE:WE ARE:
Gary Trakhman
Software Engineer at
@gtrakGT
Revelytix, Inc.
Jason Lewis
CTO at
@canweriotnow
An Estuary, LLC