clojure 1.1 and beyond
DESCRIPTION
A rundown of the new features for Clojure v1.1 and expected features for v1.2 and beyond.TRANSCRIPT
Clojure 1.1 andBeyond
Deprecationswatchersadd-classpath
^
clojure.parallel
clojure.lang.Repl, clojure.lang.Script
Watchers
Functions add-watcher and remove-watcher are gone.
Replaced by add-watch and remove-watch.
(def x (ref 0))
(add-watch x :change (fn [key r old new] (println old " -> " new)))
(dosync (alter x inc)); 0 -> 1;=> 1
(remove-watch x :change)(dosync (alter x inc));=> 2
highlight: clojure
add-classpath
Used to be able to do insane things like:
(add-classpath "http://github.com/fogus/polyglot/raw/master/reading/onlisp/")(require '[prolog :as pro])(pro/fact painter reynolds joshua english)(pro/db-query 'painter) ;=> ((reynolds joshua english))
highlight: clojure
You should feel unclean by this.
^
Deprecated, use meta instead:
(def x (with-meta [1 2] {:in-love? true}))^x;=> {:in-love? true}
(meta x);=> {:in-love? true}
highlight: clojure
This is so that ^ can eventually become the type hint reader macro.
clojure.parallel
clojure.parallel is being re-worked to use the Java 7 fork-join library. You cantrack progress or contribute on Clojure's par branch.
http://github.com/richhickey/clojure/tree/par
REPL and Scripts
clojure.lang.Repl and clojure.lang.Script have been replaced by clojure.main.
java -cp clojure.jar clojure.main # REPLjava -cp clojure.jar clojure.main -i script.clj -r # REPL, load script.clj on startupjava -cp clojure.jar clojure.main script.clj # Run scriptjava -cp clojure.jar clojure.main -e '(+ 1 41)' # Eval stringjava -cp clojure.jar clojure.main - # Run with stdin
highlight: clojure
AdditionsPrimitive Array Generation and CastingChunked SequencesFuturesPromisesTransientsFunction pre- and post- conditionsUser-controlled Thread Bindings (not discussed)Ref History (not discussed)New NamespacesMiscellaneous
Primitive Array Generation
boolean-array, byte-array, char-array, and short-array
(def x (byte-array [(byte 0x71) (byte 0x75) (byte 0x78)]))(String. x);=> "qux"
highlight: clojure
Primitive Array Casting
booleans, bytes, chars, shorts
Chunked Sequences
Making sequence operations more efficient since v1.1!
What is the Granularity of Laziness and Sequential Processing?
Prior to 1.1 the answer was 1 element at a time.
For 1.1 and beyond the answer is 1 chunk at a time.
A Chunk at a Time
Advantages of Chunkiness
Still works on the 1-at-a-time modelAligns with the underlying data structuresAmortizes the overhead of sequential access
Once every 32 timesStill avoids full realization
Disadvantage
Eliminates full lazinessAlthough an API for 1-at-a-time laziness is in the works
More Information
http://bit.ly/chunked
Futures
Asynchronous computations occuring in other threads that will block if theexpression has not finished. All subsequent dereferencing will return thecalculated value.
(let [x (future (do (Thread/sleep 5000) (+ 41 1)))] @x) ; ... 5 seconds later;=> 42
highlight: clojure
Also useful: future-call, future?, future-done?, future-cancel, future-cancelled?.
Promise / Deliver
A hand-off reference used to deliver a value from one thread to another. Anyattempt to dereference will block until "delivery".
(def x (promise))(.start (Thread. #(do (Thread/sleep 5000) (deliver x "Dear John"))))@x; ... 5 seconds later;=> "Dear John"
highlight: clojure
Transients
Provides a mutable subset of functions to use on transient versions of thestandard collection types.
Used on locals only and only on vectors, hash-maps, and hash-setsSupport the read-only functionstransient, persistent!, conj!, assoc!, dissoc!, pop!, disj! to mutateThread-safe. Modification attempt in a different thread throws an execption
Here is a transient version of concat:
(defn zen-cat [x y] (loop [src y, ret (transient x)] (if src (recur (next src) (conj! ret (first src))) (persistent! ret))))
(zen-cat [1 2 3] [4 5 6]);=> [1 2 3 4 5 6]
highlight: clojure
Rememeber to call persistent! before returning your transient only if youintend to give out a mutable version:
(persistent! (conj! (zen-cat [1 2 3] [4 5 6]) 7)) ;; assume just ret on return;=> [1 2 3 4 5 6 7]
highlight: clojure
:pre and :post
Sets constraints on the input and output of a function.
(defn constrained-fn [f x] {:pre [(pos? x)] :post [(= % (* 2 x))]} (f x))
(constrained-fn #(* 2 %) 2);=> 4
(constrained-fn #(* 2 %) -2); java.lang.AssertionError: Assert failed: (pos? x)
(constrained-fn #(* 3 %) 2); java.lang.AssertionError: Assert failed: (= % (* 2 x))
highlight: clojure
New Namespaces
clojure.test
clojure.test.junit
clojure.stacktrace
clojure.walk
clojure.template
Misc.
juxt
((juxt a b c) x) => [(a x) (b x) (c x)]
((juxt + *));=> [0 1]
((juxt - /) 2);=> [-2 1/2]
highlight: clojure
Clojure 1.2 (probably)
reify
deftype
defprotocol
Fine-grained locals clearingAgent error handlers
Clojure 1.?
Clojure in ClojureIO streams (not discussed)Chunked sequence API (not discussed)Program verification via Datalog (not discussed)Finger trees (read The Joy of Clojure)
Reify -- aka newnew
Like proxy, except:
Only protocols or interfacesMethod bodies are true methods and not external functions
No dynamic swapping of methodsMust be AOT'd
Deftype
Dynamically generates bytecode for an anonymous class with some fields and a type slotMight also generate methods for protocols or interfacesCan be AOT'd for extra benefits
Like defstruct, except:
Generates a class with fields, no map lookupsFaster field lookupHas a proper type slotFields can be primitive and hintedCan implement any number of protocols or interfaces
More Information
http://bit.ly/clj-types
Protocols
The best of interfaces
Signatures onlyMultiple implements
Without the mold
Which interfaces to implement are defined along with the typeAvoids isa/instanceof and heirarchies
And Even Better
Allows independent extensionSingle dispatch on type
More Information
http://bit.ly/clj-protocols
Fine-grained Locals Clearing(let [r (range 1e9)] [(first r) (last r)]); java.lang.OutOfMemoryError: Java heap space
highlight: clojure
No need for strict tail-position adherence!
More Information
http://bit.ly/luz-ur-head
Agent Error Queues
Since agent actions are run in other thread(s), what happens if exceptions arethrown?
Currently
Exceptions are stored in the agent itself and accessed/cleared by agent-errors/clear-agent-errors
Future
Callbacks provided a queue of errors and react based on :continue and :failerror modes
More information
http://bit.ly/clj-aeh
Clojure in Clojure (cinc)
Clojure is three parts:
1. The compiler -- JAVA2. The data structures -- JAVA (mostly)3. clojure.core+ -- CLOJURE
Clojure in Clojure is the effort to replace the Java bits above with Clojurewithout losing the JVM.
Toward Clojure in Clojure
reify is of the utmost importance
We could use proxy and gen-class but too slow
The compiler and reader could be written in Clojure today
But first types and protocols should be rolled out
Why Clojure in Clojure?
PortingNo need to port the structuresOnly (relatively) tiny bits of the compiler
Description of Clojure's special formsUsing the JVM to bootstrap other platform targets
But What is Clojure?
Too philosophical for this talk.
More Information
http://blog.n01se.net/?p=41
Questions?
http://joyofclojure.com
http://manning.com/fogus
Order today with code 'j1337' and get a whopping 37% off!