5. Kill the 'return', last thing's always returned.
Welcome to Clojure.
(fn [] 5)
6. Move the left parenthesis over a bit more...
Done.
someFunction(arg1, arg2, arg3);
(someFunction arg1 arg2 arg3)
CALLING STUFFCALLING STUFF
7. THIS ISN'T AN ACCIDENTTHIS ISN'T AN ACCIDENT
Javascript is 'Lisp in C's Clothing'
Says Crockford:
http://www.crockford.com/javascript/javascript.html
8. PUT ANOTHER WAY...PUT ANOTHER WAY...
Q: Why do you think we've gotten so much mileage out of
javascript?
A: Lisp is very powerful, and it will never die
9. 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
11. ANYTHING CAN BE A KEY, BECAUSEANYTHING CAN BE A KEY, BECAUSE
1. Every object is also a 'value'
2. Values have true equality
3. Values Never Change (Immutability)
4. Without immutability, objects are just buckets in memory
...have you ever trusted a bucket with no values?
12. Q: Why is this big news?
A: I can write code and rest assured that other parts of my
program can't change the data that I'm working on.
Q: But I thought every program is simply a short-lived http
request handler that talks to a database? We just throw the
program state out after every request!
A: Well, that's one way to do it.
15. NODE.JS... IS NOTHING NEWNODE.JS... IS NOTHING NEW
We can write our own loops
Node.js assumes threaded programming is hard, and
throws out the baby with the bath-water
Threaded programming is hard without real 'Data' or
'Values'
Composition of any sort is simpler with data
16. APPROXIMATING NODE.JSAPPROXIMATING NODE.JS
'Agents' are asynchronous queues, sharing threadpools to
do 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)]))
19. WHAT WE REALLY WANTWHAT WE REALLY WANT
Tools that let us
1. Compose Systems
2. Change our minds
3. Re-use components in different contexts, processes,
servers, etc..
Data/Values give us the ability to decouple things easily
22. 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
23. Everybody likes chaining, right?
How is this implemented? Is this reusable?
$("#p1").css("color","red").slideUp(2000).slideDown(2000);
24. What if, as a library author, you could just not write that fluent
interface 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")
25. 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 powerful
languages. Leads to simple, composable libraries.
26. 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
27. 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)
28. CALL TO ACTIONCALL TO ACTION
1. Learn Clojure
2. Build cool things
3. Screencasts!
(You ruby guys really know how to make good screencasts)
29. DEMO TIMEDEMO TIME
CLOJURE ON THE WEBCLOJURE ON THE WEB
Now clone this:
https://github.com/canweriotnow/bohjure
30. RESOURCESRESOURCES
Clojure: http://clojure.org
Fun Exercises: http://www.4clojure.com
Cheatsheets: http://clojure.org/cheatsheet
Building: https://github.com/technomancy/leiningen
Insight: http://www.youtube.com/user/ClojureTV
Community docs: http://clojuredocs.org
Blogs: http://planet.clojure.in
Light Table: http://www.lighttable.com
this doc: http://gtrak.github.io/bohconf.clojure
32. 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