Clojure Deep Dive

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

0 comments

Post a comment

    Post a comment
    Embed Video
    Edit your comment Cancel

    2 Favorites

    Clojure Deep Dive - Presentation Transcript

    1. Clojure Deep Dive Howard M. Lewis Ship TWD Consulting hlship@gmail.com 1 © 2009 Howard Lewis Ship
    2. Agenda • Core Language • Standard Tools • Clojure Compilation • Clojure Pitfalls 2 © 2009 Howard Lewis Ship
    3. Core Language 3 © 2009 Howard Lewis Ship
    4. What's A Form? Constants: Keywords: Symbols: 42 :foo map "hello" :tag strutils2/take Data Structures: […] {…} #{ … } Callables: Special Forms: Function Call: Macros Expansion: (if …) (map …) (and …) (var …) (or …) (do …) (ns …) 4 © 2009 Howard Lewis Ship
    5. defn: Define a function Symbol (in current namespace) Optional doc string (defn to-seq "Converts the object to a sequence (a vector) unless it is already sequential." [obj] (if (sequential? obj) obj [obj])) List of parameters user=> (doc to-seq) ------------------------- user/to-seq ([obj]) Converts the object to a sequence (a vector) unless it is already sequential. nil user=> 5 © 2009 Howard Lewis Ship
    6. defn: Multiple Arities One doc string Series of argument lists / forms (defn not= "Same as (not (= obj1 obj2))" ([x] false) ([x y] (not (= x y))) ([x y & more] (not (apply = x y more)))) & symbol ➠ provide remaining values as a seq user=> (doc not=) ------------------------- clojure.core/not= ([x] [x y] [x y & more]) Same as (not (= obj1 obj2)) nil user=> 6 © 2009 Howard Lewis Ship
    7. let: local symbols (let [center (calc-center-for-frame frame) x (get-x center) y (get-y center)] …) •Even number: symbol1 form1 symbol2 form2 … •Not variables: symbols are read-only •Can re-define symbols 7 © 2009 Howard Lewis Ship
    8. do: evaluate for side-effects (if value-found (do (println "Found the value.") value-found)) Last form is the result ; Broken (if value-found (println "Found the value.") If true, side effect & return nil value-found) If false, return value (false or nil) 8 © 2009 Howard Lewis Ship
    9. Branching: if, when (if test then-form) (if test then-form else-form) • Special form: not a function • Evaluates test, then evaluates & returns either then-form or else-form • false and nil ➠ logical false • anything else ➠ logical true (when test then-forms) (if-not test then-form) (if-not test then-form else-form) Any number of forms in an implicit do Like (if (not test) then else) (when-not test then-forms) 9 © 2009 Howard Lewis Ship
    10. if-let, when-let (if-let [symbol test] then-form) (if-let [symbol test] then-form else-form) Symbol can be referenced (when-let [symbol test] then-forms) Any number of forms in an implicit do 10 © 2009 Howard Lewis Ship
    11. or, and (or form…) (and form…) • or: first value from list that evaluates to true • Will return value of last expression (false or nil) • (or) returns nil • and: first logical false (nil or false) • Returns value of last expression (if prior are logical true) • (and) return true • Can be used as a "guard" Only invoke symbol and find-ns (defn dispatch-named-function-to-pipeline if ns-name is non-nil [env pipeline] (let [split-path (-> env :cascade :split-path) [_ ns-name fn-name] split-path fn-namespace (and ns-name (find-ns (symbol ns-name))) named-function (and fn-namespace fn-name (ns-resolve fn-namespace (symbol fn-name))) new-env (assoc-in env [:cascade :extra-path] (drop 3 split-path))] (call-pipeline pipeline new-env named-function))) 11 © 2009 Howard Lewis Ship
    12. Destructuring Bu N wo sy o rk • Automatically extract values from data structures ! • Binding forms: • Map to extract keys • Vector to extract indexed values • Function parameters One un-named parameter • let, if-let, when-let, etc. destructured to two symbols user=> (defn natural-name [{fname :first-name lname :last-name}] (str lname ", " fname)) #'user/natural-name user=> (natural-name (persons 1)) "Simon, Scott" user=> 12 © 2009 Howard Lewis Ship
    13. Destructuring • Binding Forms: • symbol (let [x (get-x center)] … ) • vector of binding forms (let [[x y] center] … ) • map of binding form to map key (let [{fname :first-name lname :last-name} person] …) 13 © 2009 Howard Lewis Ship
    14. Vector Destructuring center must be sequential (let [[x y] center] …) May be nil if not enough values in center (let [[first-born second-born & other-children] children] …) & symbol gets the remaining values (let [[first-born second-born & other-children :as children] (find-children parent)] …) Nested binding forms! :as symbol gets the full list user=> (let [[[x1 y1][x2 y2]] [[1 2] [3 4]]] [x1 y1 x2 y2]) [1 2 3 4] user=> 14 © 2009 Howard Lewis Ship
    15. Map Destructuring (defn natural-name [{fname :first-name lname :last-name}] (str lname ", " fname)) (defn natural-name [{:keys [first-name last-name]}] (str last-name ", " first-name)) :keys maps a keyword key for each symbol :or sets defaults for missing keys user=> (defn natural-name [{:keys [first-name last-name] :or {first-name "(none)" last-name "(none)"}}] (str last-name ", " first-name)) #'user/natural-name user=> (natural-name {:first-name "Gromit"}) "(none), Gromit" user=> (natural-name {:first-name "Gromit" :last-name nil}) ", Gromit" user=> :as symbol to get the original map :strs ➠ like :keys, but maps to string keys, not keyword keys :syms ➠ like :keys, but maps to symbol keys, not keyword keys 15 © 2009 Howard Lewis Ship
    16. ns: define namespaces (ns example.utils) cascade/dispatcher.clj (ns cascade.dispatcher (:import (javax.servlet ServletResponse)) File: example/utils.clj (:use (cascade config dom logging path-map pipeline) (cascade.internal utils))) (ns namespace (:import …) Optional directives (:use …)) user=> (defn natural-name [{fname :first-name lname :last-name}] (str lname ", " fname)) #'user/natural-name user=> (natural-name (persons 1)) "Simon, Scott" user=> user/natural-name Namespace: user Symbol: natural-name 16 © 2009 Howard Lewis Ship
    17. :import Java Classes Package name, then any number of classes/interfaces (ns cascade.dispatcher (:import (javax.servlet ServletResponse)) …) Repeat for other packages Can also list fully qualify class names 17 © 2009 Howard Lewis Ship
    18. :use Import Namespaces (:use clojure.contrib.pprint) Symbols defined by pprint are available, i.e. (pprint [1 2 3]) (:use (clojure.contrib pprint monads)) Add multiple namespaces under the root namespace (:use (clojure.contrib (str-utils2 :only [join map-str])) Uses just join and map-str from str-utils2 (:use (clojure.contrib (str-utils2 :exclude [take replace drop])) Exclude just some of the symbols (:use (clojure.contrib (str-utils2 :rename {take strtake})) Use str-utils2, mapping take as strtake 18 © 2009 Howard Lewis Ship
    19. Other ns directives • :require ➠ load a namespace but don't import it • :gen-class ➠ create a Java class from functions in the namespace • :refer-clojure ➠ import selected clojure.core symbols • :load ➠ load Clojure scripts (not namespaces) 19 © 2009 Howard Lewis Ship
    20. Standard Tools 20 © 2009 Howard Lewis Ship
    21. Anonymous Functions #() ➠ implicit anonymous function (filter #(not (.startsWith % ".")) names) % is replaced by the function's parameter %n is parameter #n (map #(assoc %1 :sort-index %2) (sort-by :age persons) (iterate inc 0)) inline anonymous function (map 21 (fn [person-map sort-index] (assoc person-map :sort-index sort-index)) (sort-by :age persons) (iterate inc 0)) © 2009 Howard Lewis Ship
    22. What are seqs? Seqable seq() : ISeq IPersistentCollection Sequential count() : int cons(Object): IPersistentCollection empty() : IPersistentCollection equiv(Object) : boolean PersistentSet ISeq first() : Object next(): ISeq more(): ISeq cons(Object): ISeq Returned from map, for, filter, remove, etc. PersistentList PersistentVector LazySeq 22 © 2009 Howard Lewis Ship
    23. assoc-in / update-in user=> (def person { :first-name "Howard" :last-name "Lewis Ship" :address { :street "123 NW 12th Ave. #541" :city "Portland" :state "OR" :zip 97309 }}) #'user/person user=> (assoc-in person [:address :street] "2647 SE 97th Ave.") {:first-name "Howard", :last-name "Lewis Ship", :address {:street "2647 SE 97th Ave.", :city "Portland", :state "OR", :zip 97309}} user=> (update-in person [:address :zip] + 5) {:first-name "Howard", :last-name "Lewis Ship", :address {:street "123 NW 12th Ave. #541", :city "Portland", :state "OR", :zip 97314}} user=> :first-name "Howard" :last-name "Lewis Ship" :address :street "123 NW 12th Ave." :city "Portland" :state "OR" :zip 97309 (update-in person [:address :zip] + 5) (+ 97309 5) :first-name "Howard" :last-name "Lewis Ship" :address :street "123 NW 12th Ave." :city "Portland" :state "OR" :zip 97314 23 © 2009 Howard Lewis Ship
    24. map La zy f :age acts as a function user=> (map :age persons) (42 44 29) user=> (map #(apply str (reverse (% :first-name))) persons) ("drawoH" "ttocS" "ylloM") user=> (map identity (persons 0)) ([:first-name "Howard"] iterate a map ➠ key/value pairs [:last-name "Lewis Ship"] [:age 42]) user=> (seq (persons 0)) ([:first-name "Howard"] [:last-name "Lewis Ship"] [:age 42]) user=> 24 © 2009 Howard Lewis Ship
    25. map La zy f N seqs ➠ N parameters user=> (map #(assoc %1 :sort-index %2) (sort-by :age persons) (iterate inc 0)) ({:sort-index 0, :first-name "Molly", :last-name "Newman", :age 29} {:sort-index 1, :first-name "Howard", :last-name "Lewis Ship", :age 42} {:sort-index 2, :first-name "Scott", :last-name "Simon", :age 44}) user=> 25 © 2009 Howard Lewis Ship
    26. reduce f user=> (map :age persons) (42 44 29 38) user=> (reduce + (map :age persons)) 153 (reduce + (map :age persons)) 26 © 2009 Howard Lewis Ship
    27. reduce f user=> (map :age persons) (42 44 29 38) user=> (reduce + (map :age persons)) 153 (reduce + (map :age persons)) (reduce + '(42 44 29 38)) 27 © 2009 Howard Lewis Ship
    28. reduce f user=> (map :age persons) (42 44 29 38) user=> (reduce + (map :age persons)) 153 (reduce + (map :age persons)) (reduce + '(42 44 29 38)) (+ (+ (+ 42 44) 29) 38) 28 © 2009 Howard Lewis Ship
    29. reduce f user=> (map :age persons) (42 44 29 38) user=> (reduce + (map :age persons)) 153 (reduce + (map :age persons)) (reduce + '(42 44 29 38)) (+ (+ (+ 42 44) 29) 38) (+ (+ 86 29) 38) 29 © 2009 Howard Lewis Ship
    30. reduce f user=> (map :age persons) (42 44 29 38) user=> (reduce + (map :age persons)) 153 (reduce + (map :age persons)) (reduce + '(42 44 29 38)) (+ (+ (+ 42 44) 29) 38) (+ (+ 86 29) 38) (+ 115 38) 30 © 2009 Howard Lewis Ship
    31. reduce f user=> (map :age persons) (42 44 29 38) user=> (reduce + (map :age persons)) 153 (reduce + (map :age persons)) (reduce + '(42 44 29 38)) (+ (+ (+ 42 44) 29) 38) (+ (+ 86 29) 38) (+ 115 38) 153 31 © 2009 Howard Lewis Ship
    32. reduce f user=> (def input-string "Clojure is a fascinating language with unique capabilities and total integration with Java.") #'user/input-string user=> (seq input-string) (C l o j u r e space i s space a space f a s c i n a t i n g space l a n g u a g e space w i t h space u n i q u e space c a p a b i l i t i e s space a n d space t o t a l space i n t e g r a t i o n space w i t h space J a v a .) user=> (reduce (fn [m k] (update-in m [k] #(if (nil? %) 1 (inc %)))) Optional initial value {} (seq input-string)) {space 12, a 12, b 1, C 1, c 2, d 1, e 5, f 1, g 4, h 2, i 11, J 1, j 1, l 4, . 1, n 7, o 3, p 1, q 1, r 2, s 3, t 8, u 4, v 1, w 2} user=> 32 © 2009 Howard Lewis Ship
    33. filter / remove La zy f ? user=> (remove #(< (% :age) 30) persons) ({:first-name "Howard", :last-name "Lewis Ship", :age 42} {:first-name "Scott", :last-name "Simon", :age 44}) user=> (filter #(< (% :age) 30) persons) ({:first-name "Molly", :last-name "Newman", :age 29}) user=> 33 © 2009 Howard Lewis Ship
    34. apply f user=> (map :age persons) (42 44 29) user=> (apply + (map :age persons)) 115 user=> (apply + (map :age persons)) (apply + '(42 44 29)) (+ 42 44 29) 115 34 © 2009 Howard Lewis Ship
    35. Clojure Compilation 35 © 2009 Howard Lewis Ship
    36. Function Calls (remove nil? coll) IFn invoke() : Object invoke(Object) : Object Namespace invoke(Object, Object) : Object … applyTo(ISeq) : Object Var get() clojure.core$remove__4782 PersistentMap Keyword 36 © 2009 Howard Lewis Ship
    37. Compiled to Bytecode (defn first-non-nil "Returns the first non-nil value from the collection." [coll] (first (remove nil? coll))) package com.howardlewisship.cascade.internal; import clojure.lang.*; public class utils$first_non_nil__24 extends AFunction { public Object invoke(Object coll) throws Exception { return ((IFn)const__0.get()).invoke(((IFn)const__1.get()). invoke(const__2.get(), coll = null)); } public static final Var const__0 = (Var)RT.var("clojure.core", "first"); public static final Var const__1 = (Var)RT.var("clojure.core", "remove"); public static final Var const__2 = (Var)RT.var("clojure.core", "nil?"); public utils$first_non_nil__24() { } } 37 © 2009 Howard Lewis Ship
    38. Compiled to Bytecode (defn first-non-nil "Returns the first non-nil value from the collection." [coll] (first (remove nil? coll))) package com.howardlewisship.cascade.internal; import clojure.lang.*; public class utils$first_non_nil__24 extends AFunction { public Object invoke(Object coll) throws Exception { return ((IFn)const__0.get()).invoke(((IFn)const__1.get()). invoke(const__2.get(), coll = null)); } public static final Var const__0 = (Var)RT.var("clojure.core", "first"); public static final Var const__1 = (Var)RT.var("clojure.core", "remove"); public static final Var const__2 = (Var)RT.var("clojure.core", "nil?"); public utils$first_non_nil__24() { } } 38 © 2009 Howard Lewis Ship
    39. Compiled to Bytecode (defn first-non-nil "Returns the first non-nil value from the collection." [coll] (first (remove nil? coll))) package com.howardlewisship.cascade.internal; import clojure.lang.*; public class utils$first_non_nil__24 extends AFunction { public Object invoke(Object coll) throws Exception { return ((IFn)const__0.get()).invoke(((IFn)const__1.get()). invoke(const__2.get(), coll = null)); } public static final Var const__0 = (Var)RT.var("clojure.core", "first"); public static final Var const__1 = (Var)RT.var("clojure.core", "remove"); public static final Var const__2 = (Var)RT.var("clojure.core", "nil?"); public utils$first_non_nil__24() { } } 39 © 2009 Howard Lewis Ship
    40. Compiled to Bytecode (defn first-non-nil "Returns the first non-nil value from the collection." [coll] (first (remove nil? coll))) package com.howardlewisship.cascade.internal; import clojure.lang.*; public class utils$first_non_nil__24 extends AFunction { public Object invoke(Object coll) throws Exception { return ((IFn)const__0.get()).invoke(((IFn)const__1.get()). invoke(const__2.get(), coll = null)); } public static final Var const__0 = (Var)RT.var("clojure.core", "first"); public static final Var const__1 = (Var)RT.var("clojure.core", "remove"); public static final Var const__2 = (Var)RT.var("clojure.core", "nil?"); public utils$first_non_nil__24() { } } 40 © 2009 Howard Lewis Ship
    41. Compiled to Bytecode (defn format-date [env params] (let [#^Date date (params :date) package app1; #^DateFormat fmt (DateFormat/getDateTimeInstance DateFormat/MEDIUM import clojure.lang.*; DateFormat/MEDIUM)] import java.text.DateFormat; (.format fmt date))) import java.util.Date; public class fragments$format_date__21 extends AFunction { public Object invoke(Object env, Object params) throws Exception { Object date = ((IFn)params).invoke(const__1); Object fmt = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM); env = null; params = null; date = null; fmt = null; return ((DateFormat)fmt).format((Date)date); } public static final Var const__0 = (Var)RT.var("clojure.core", "let"); public static final Object const__1 = Keyword.intern(Symbol.create(null, "date")); public fragments$format_date__21() { } } 41 © 2009 Howard Lewis Ship
    42. Compiled to Bytecode (defn format-date [env params] (let [#^Date date (params :date) package app1; #^DateFormat fmt (DateFormat/getDateTimeInstance DateFormat/MEDIUM import clojure.lang.*; DateFormat/MEDIUM)] import java.text.DateFormat; (.format fmt date))) import java.util.Date; public class fragments$format_date__21 extends AFunction { public Object invoke(Object env, Object params) throws Exception { Object date = ((IFn)params).invoke(const__1); Object fmt = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM); env = null; params = null; date = null; fmt = null; return ((DateFormat)fmt).format((Date)date); } public static final Var const__0 = (Var)RT.var("clojure.core", "let"); public static final Object const__1 = Keyword.intern(Symbol.create(null, "date")); public fragments$format_date__21() { } } 42 © 2009 Howard Lewis Ship
    43. Compiled to Bytecode (defn format-date [env params] (let [#^Date date (params :date) package app1; #^DateFormat fmt (DateFormat/getDateTimeInstance DateFormat/MEDIUM import clojure.lang.*; DateFormat/MEDIUM)] import java.text.DateFormat; (.format fmt date))) import java.util.Date; public class fragments$format_date__21 extends AFunction { public Object invoke(Object env, Object params) throws Exception { Object date = ((IFn)params).invoke(const__1); Object fmt = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM); env = null; params = null; date = null; fmt = null; return ((DateFormat)fmt).format((Date)date); } public static final Var const__0 = (Var)RT.var("clojure.core", "let"); public static final Object const__1 = Keyword.intern(Symbol.create(null, "date")); public fragments$format_date__21() { } } 43 © 2009 Howard Lewis Ship
    44. Compiled to Bytecode (defn format-date [env params] (let [#^Date date (params :date) package app1; #^DateFormat fmt (DateFormat/getDateTimeInstance DateFormat/MEDIUM import clojure.lang.*; DateFormat/MEDIUM)] import java.text.DateFormat; (.format fmt date))) import java.util.Date; public class fragments$format_date__21 extends AFunction { public Object invoke(Object env, Object params) throws Exception { Object date = ((IFn)params).invoke(const__1); Object fmt = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM); env = null; params = null; date = null; fmt = null; return ((DateFormat)fmt).format((Date)date); } public static final Var const__0 = (Var)RT.var("clojure.core", "let"); public static final Object const__1 = Keyword.intern(Symbol.create(null, "date")); public fragments$format_date__21() { } } 44 © 2009 Howard Lewis Ship
    45. Compiled to Bytecode (defn format-date [env params] (let [#^Date date (params :date) package app1; #^DateFormat fmt (DateFormat/getDateTimeInstance DateFormat/MEDIUM import clojure.lang.*; DateFormat/MEDIUM)] import java.text.DateFormat; (.format fmt date))) import java.util.Date; public class fragments$format_date__21 extends AFunction { public Object invoke(Object env, Object params) throws Exception { Object date = ((IFn)params).invoke(const__1); Object fmt = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM); env = null; params = null; date = null; fmt = null; return ((DateFormat)fmt).format((Date)date); } public static final Var const__0 = (Var)RT.var("clojure.core", "let"); public static final Object const__1 = Keyword.intern(Symbol.create(null, "date")); public fragments$format_date__21() { } } 45 © 2009 Howard Lewis Ship
    46. Ahead of Time Compilation app/fragments.clj (ns app.fragments (:import (java.util Date) (java.text DateFormat))) (defn format-date [env params] (…)) Compiler app/fragments__init.class app/fragments$format_date__21.class 46 © 2009 Howard Lewis Ship
    47. Ahead Of Time Compilation build.xml <target name="compile" description="Compile Clojure sources."> <mkdir dir="${classes.dir}" /> <pathconvert pathsep=" " property="compile.namespaces"> <fileset dir="${src.dir}" includes="**/*.clj" /> <chainedmapper> <packagemapper from="${basedir}/${src.dir}/*.clj" to="*" /> <filtermapper> <replacestring from="_" to="-" /> </filtermapper> </chainedmapper> </pathconvert> <java classname="clojure.lang.Compile"> <classpath> <path refid="libs.path" /> <path location="${classes.dir}" /> <path location="${src.dir}" /> </classpath> <sysproperty key="clojure.compile.path" value="${classes.dir}" /> <arg line="${compile.namespaces}" /> </java> </target> 47 © 2009 Howard Lewis Ship
    48. Ahead Of Time Compilation build.xml <target name="compile" description="Compile Clojure sources."> <mkdir dir="${classes.dir}" /> <pathconvert pathsep=" " property="compile.namespaces"> <fileset dir="${src.dir}" includes="**/*.clj" /> <chainedmapper> <packagemapper from="${basedir}/${src.dir}/*.clj" to="*" /> <filtermapper> <replacestring from="_" to="-" /> </filtermapper> Locate *.clj under </chainedmapper> ${src.dir} and convert to </pathconvert> namespace names <java classname="clojure.lang.Compile"> <classpath> <path refid="libs.path" /> <path location="${classes.dir}" /> <path location="${src.dir}" /> </classpath> <sysproperty key="clojure.compile.path" value="${classes.dir}" /> <arg line="${compile.namespaces}" /> </java> </target> 48 © 2009 Howard Lewis Ship
    49. Ahead Of Time Compilation build.xml <target name="compile" description="Compile Clojure sources."> <mkdir dir="${classes.dir}" /> <pathconvert pathsep=" " property="compile.namespaces"> <fileset dir="${src.dir}" includes="**/*.clj" /> <chainedmapper> <packagemapper from="${basedir}/${src.dir}/*.clj" to="*" /> <filtermapper> <replacestring from="_" to="-" /> </filtermapper> </chainedmapper> </pathconvert> clojure.jar, source <java classname="clojure.lang.Compile"> directory and output <classpath> directory must be on <path refid="libs.path" /> classpath <path location="${classes.dir}" /> <path location="${src.dir}" /> </classpath> <sysproperty key="clojure.compile.path" value="${classes.dir}" /> <arg line="${compile.namespaces}" /> </java> </target> 49 © 2009 Howard Lewis Ship
    50. Ahead Of Time Compilation build.xml <target name="compile" description="Compile Clojure sources."> <mkdir dir="${classes.dir}" /> <pathconvert pathsep=" " property="compile.namespaces"> <fileset dir="${src.dir}" includes="**/*.clj" /> <chainedmapper> <packagemapper from="${basedir}/${src.dir}/*.clj" to="*" /> <filtermapper> <replacestring from="_" to="-" /> </filtermapper> </chainedmapper> </pathconvert> Output directory for <java classname="clojure.lang.Compile"> generated classes <classpath> <path refid="libs.path" /> <path location="${classes.dir}" /> <path location="${src.dir}" /> </classpath> <sysproperty key="clojure.compile.path" value="${classes.dir}" /> <arg line="${compile.namespaces}" /> </java> </target> List of namespaces to compile 50 © 2009 Howard Lewis Ship
    51. Clojure Pitfalls 51 © 2009 Howard Lewis Ship
    52. IDE Support 52 © 2009 Howard Lewis Ship
    53. Laziness RuntimeException: Divide by zero 53 © 2009 Howard Lewis Ship
    54. Laziness Clojure 1.0.0- 1:1 user=> (def nums (map / (range 0 10) (reverse (range 0 10)))) #'user/nums 1:2 user=> nums java.lang.ArithmeticException: Divide by zero (0 1/8 2/7 1/2 4/5 5/4 2 7/2 1:3 user=> (.. *e getCause printStackTrace) java.lang.ArithmeticException: Divide by zero at clojure.lang.Numbers.divide(Numbers.java:138) at clojure.core$_SLASH___3350.invoke(core.clj:575) at clojure.core$map__3815$fn__3822.invoke(core.clj:1508) at clojure.lang.LazySeq.seq(LazySeq.java:41) at clojure.lang.Cons.next(Cons.java:37) at clojure.lang.RT.next(RT.java:560) at clojure.core$next__3117.invoke(core.clj:50) at clojure.core$nthnext__4405.invoke(core.clj:2531) at clojure.core$print_sequential__5354.invoke(core_print.clj:53) at clojure.core$fn__5439.invoke(core_print.clj:136) at clojure.lang.MultiFn.invoke(MultiFn.java:161) at clojure.core$pr_on__4145.invoke(core.clj:2020) at clojure.core$pr__4148.invoke(core.clj:2030) at clojure.lang.AFn.applyToHelper(AFn.java:173) at clojure.lang.RestFn.applyTo(RestFn.java:137) at clojure.core$apply__3243.doInvoke(core.clj:390) at clojure.lang.RestFn.invoke(RestFn.java:428) at clojure.core$prn__4159.doInvoke(core.clj:2053) at clojure.lang.RestFn.invoke(RestFn.java:413) at clojure.main$repl__5813$read_eval_print__5825.invoke(main.clj:177) at clojure.main$repl__5813.doInvoke(main.clj:193) at clojure.lang.RestFn.invoke(RestFn.java:876) at clojure.contrib.repl_ln$repl__84.doInvoke(repl_ln.clj:259) at clojure.lang.RestFn.invoke(RestFn.java:426) at clojure.contrib.repl_ln$_main__44.doInvoke(repl_ln.clj:136) at clojure.lang.RestFn.applyTo(RestFn.java:142) at clojure.contrib.repl_ln.main(Unknown Source) nil 1:7 user=> 54 © 2009 Howard Lewis Ship
    55. Lack of Type Checking 55 © 2009 Howard Lewis Ship
    56. Spot the Error view_manager.clj (defn to-dom-node-seq [any] "Converts the result of a render function to a seq as needed." (cond (nil? any) nil (sequential? any) any ; A map is assumed to be a DOM node, wrap it in a vector (map? any) [map] (string? any) [(struct-map dom-node :type :text :value any)] true (throw (RuntimeException. (format "A rendering function returned %s. ↵ Rendering functions should return nil, a string, a seq of DOM nodes, or a single ↵ DOM node." (pr-str any)))))) 56 © 2009 Howard Lewis Ship
    57. Exception ERROR in (simple-view-and-fragment) (test_is.clj:657) Uncaught exception, not in assertion. expected: nil actual: java.lang.IllegalArgumentException: Wrong number of args passed to: core$map at clojure.lang.AFn.throwArity (AFn.java:449) clojure.lang.RestFn.invoke (RestFn.java:417) com.howardlewisship.cascade.dom$fn__960.doInvoke (dom.clj:58) clojure.lang.RestFn.invoke (RestFn.java:443) clojure.lang.MultiFn.invoke (MultiFn.java:165) com.howardlewisship.cascade.dom/render_xml_with_ns (dom.clj:118) com.howardlewisship.cascade.dom/render_xml (dom.clj:125) com.howardlewisship.cascade.test_views/render (test_views.clj:27) com.howardlewisship.cascade.test_views/test_view (test_views.clj:56) com.howardlewisship.cascade.test_views/test_view (test_views.clj:52) com.howardlewisship.cascade.test_views/fn (test_views.clj:62) dom.clj (defmulti render-node-xml (fn [node & rest] (node :type))) 57 © 2009 Howard Lewis Ship
    58. Spot the Error view_manager.clj (defn to-dom-node-seq [any] "Converts the result of a render function to a seq as needed." (cond (nil? any) nil (sequential? any) any ; A map is assumed to be a DOM node, wrap it in a vector (map? any) [map] (string? any) [(struct-map dom-node :type :text :value any)] true (throw (RuntimeException. (format "A rendering function returned %s. ↵ Rendering functions should return nil, a string, a seq of DOM nodes, or a single ↵ DOM node." (pr-str any)))))) Returning function clojure.core/map; should return any (the parameter) 58 © 2009 Howard Lewis Ship
    59. Bus Factor 59 © 2009 Howard Lewis Ship
    60. GitHub Factor 60 © 2009 Howard Lewis Ship
    61. Performance 61 © 2009 Howard Lewis Ship
    62. Performance (defn shorts-to-bytes [#^shorts src #^bytes dst words]  (loop [src-offset (int 0)         dst-offset (int 0)]    (when (< src-offset words)      (let [sample (short (aget src src-offset))]        (aset-byte dst dst-offset (byte sample))        (aset-byte dst (inc dst-offset) (byte (bit-shift-right sample 8))))      (recur (inc src-offset) (unchecked-add 2 dst-offset)))))  public static void shortsToBytes(short[] src, byte[] dst, int len)  {   int idx = 0; 900 ms   short s;   while (len-- > 0) {     s = src[idx];     dst[idx*2] = (byte)s; 675 ms     dst[idx*2+1] = (byte)(s>>>8);     idx++;   }  } 450 ms 225 ms 0 ms Java Clojure 62 © 2009 Howard Lewis Ship
    63. API Docs 63 © 2009 Howard Lewis Ship
    64. Wrap Up 64 © 2009 Howard Lewis Ship
    65. What's Not Covered? • multimethods ➠ inheritance-like function dispatch • Concurrency Support ➠ atoms, agents, refs & vars http://www.clojure.org • loop & recur ➠ iterative-style coding • clojure.contrib ➠ Community library • Macros & Meta-Programming ➠ Create the language you want inside Clojure • Tuning Clojure Performance • More …. 65 © 2009 Howard Lewis Ship
    66. Stuart Halloway Pragmatic Bookshelf http://pragprog.com/titles/shcloj/programming-clojure 66 © 2009 Howard Lewis Ship
    67. http://jnb.ociweb.com/jnb/jnbMar2009.html 67 © 2009 Howard Lewis Ship
    68. Image Credits © 2005 Jean-Philippe Daigle http://www.flickr.com/photos/jpdaigle/59942231/ © 2007 Howard Gees http://www.flickr.com/photos/cyberslayer/952121271/ © 2006 Simon Law http://www.flickr.com/photos/sfllaw/222795669/ © 2008 II-cocoy22-II http://www.flickr.com/photos/30954876@N07/3090155264/ © 2009 Martin Biskoping http://www.flickr.com/photos/mbiskoping/3388639698/ © 2008 sea turtle http://www.flickr.com/photos/sea-turtle/3049443478/ © 2009 Tulio Bertorini http://www.flickr.com/photos/tuliobertorini/3159130251/ © 2007 Adam Balch http://www.flickr.com/photos/triplemaximus/795758146/ © 2008 jessamyn west http://www.flickr.com/photos/iamthebestartist/2636607001/ 68 © 2009 Howard Lewis Ship
    SlideShare Zeitgeist 2009

    + Howard Lewis ShipHoward Lewis Ship Nominate

    custom

    524 views, 2 favs, 0 embeds more stats

    A deep dive into the core language features and fun more

    More info about this document

    © All Rights Reserved

    Go to text version

    • Total Views 524
      • 524 on SlideShare
      • 0 from embeds
    • Comments 0
    • Favorites 2
    • Downloads 0
    Most viewed embeds

    more

    All embeds

    less

    Flagged as inappropriate Flag as inappropriate
    Flag as inappropriate

    Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

    Cancel
    File a copyright complaint
    Having problems? Go to our helpdesk?

    Categories