Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

ClojureScript: The Good Parts

2,229 views

Published on

ClojureScript: The Good Parts

Published in: Software
  • Be the first to comment

ClojureScript: The Good Parts

  1. 1. ClojureScriptClojureScript The Good PartsThe Good Parts
  2. 2. カマイルカ /laʒenɔʁɛ̃k/カマイルカ /laʒenɔʁɛ̃k/ lagénorhynquelagénorhynque (defprofile lagénorhynque :name "Kent OHASHI" :languages [Clojure Haskell Python Scala English français Deutsch русский] :interests [programming language-learning mathematics] :contributing [github.com/japan-clojurians/clojure-site-ja])
  3. 3. Lisp × JavaScriptLisp × JavaScript
  4. 4. What is ClojureScript?What is ClojureScript?
  5. 5. (CLJS)(CLJS) compiler for Clojure that targets JavaScript cf. (JVM/Java), (CLR/C#) simple and powerful functional Lisp ClojureScriptClojureScript Clojure ClojureCLR
  6. 6. Use CasesUse Cases SPA: / , , , etc. React Native: Electron Node.js AWS Lambda etc. Reagent re-frame Rum Om re-natal
  7. 7. Try CLJS withTry CLJS with LumoLumo $ npm install -g lumo-cljs $ lumo cljs.user=> (defn hello [& {:keys [to] #_=> :or {to "world"}}] #_=> (println (str "Hello, " to "!"))) #'cljs.user/hello cljs.user=> (hello) Hello, world! nil cljs.user=> (hello :to "ClojureScript") Hello, ClojureScript! nil
  8. 8. Good PartsGood Parts
  9. 9. LispLisp
  10. 10. S-expressions (sexp)S-expressions (sexp) simple rule: (op arg ...) various kinds of functions macros special forms structural editing , , etc.ParEdit Parinfer
  11. 11. Collection LiteralsCollection Literals cf. function de nition cljs.user=> '(1 2 3) ; list (1 2 3) cljs.user=> [1 2 3] ; vector [1 2 3] cljs.user=> #{1 2 3} ; set #{1 2 3} cljs.user=> {:a 1 :b 2 :c 3} ; map {:a 1, :b 2, :c 3} (defn hello [& {:keys [to] :or {to "world"}}] (println (str "Hello, " to "!")))
  12. 12. Lisp MacrosLisp Macros compile-time metaprogramming code as data sexp -> sexp
  13. 13. e.g. for macro (sequence comprehension) ;; ClojureScript cljs.user=> (for [x (range 10) #_=> :when (odd? x)] #_=> (* x x)) (1 9 25 49 81) cljs.user=> (macroexpand-1 #_=> '(for [x (range 10) #_=> :when (odd? x)] #_=> (* x x))) (cljs.core$macros/let [iter__9116__auto__ (cljs.core$macros/fn ,,, # Python >>> [x ** 2 for x in range(10) if x % 2 != 0] [1, 9, 25, 49, 81] -- Haskell > [x ^ 2 | x <- [0..9], odd x] [1,9,25,49,81]
  14. 14. REPL-driven DevelopmentREPL-driven Development Create a ClojureScript project with Leiningen $ brew install leiningen $ lein new figwheel cljs-demo # e.g. "figwheel" template $ cd cljs-demo $ lein figwheel # or `cider-jack-in-clojurescript` on Emacs
  15. 15. editor-integrated REPL (e.g. Emacs & )CIDER
  16. 16. browser REPL for front-end development
  17. 17. Changes are automatically loaded in the browser
  18. 18. FunctionalFunctional ProgrammingProgramming
  19. 19. Immutable PersistentImmutable Persistent CollectionsCollections no mutations, no side e ects high performance ljs.user=> (conj [1 2] 3) ; add an element to vector [1 2 3] cljs.user=> (conj '(1 2) 3) ; add an element to list (3 1 2) cljs.user=> (conj #{1 2} 3) ; add an element to set #{1 2 3} cljs.user=> (assoc {:a 1 :b 2} :c 3) ; add an entry to map {:a 1, :b 2, :c 3}
  20. 20. Map and SequenceMap and Sequence as Core Abstractionsas Core Abstractions maps: get, assoc sequences: first, rest, cons lazy sequences rare to de ne something like classes or algebraic data types few data abstractions and many functions
  21. 21. e.g. maps for modelling entities cljs.user=> (ns geometry.sphere) nil geometry.sphere=> (defn surface-area [{::keys [radius]}] #_=> (* 4 Math/PI (Math/pow radius 2))) #'geometry.sphere/surface-area geometry.sphere=> (defn volume [{::keys [radius]}] #_=> (* 4/3 Math/PI (Math/pow radius 3))) #'geometry.sphere/volume geometry.sphere=> #::{:radius 2} #:geometry.sphere{:radius 2} geometry.sphere=> (surface-area #::{:radius 2}) 50.26548245743669 geometry.sphere=> (volume #::{:radius 2}) 33.510321638291124
  22. 22. e.g. typical sequence manipulations cljs.user=> (defn leibniz [n-terms] #_=> (->> (iterate #(+ % 2) 1) #_=> (map / (cycle [1 -1])) #_=> (take n-terms) #_=> (apply +) #_=> (* 4.0))) #'cljs.user/leibniz cljs.user=> (leibniz 1000) 3.140592653839794 cljs.user=> (leibniz 10000) 3.1414926535900345 cljs.user=> (leibniz 100000) 3.1415826535897198
  23. 23. Data > Functions > MacrosData > Functions > Macros data-driven/oriented design examples libraries: , , frameworks: , , Honey SQL Hiccup Reagent Duct Pedestal re-frame
  24. 24. speci cation system similar to Racket's cf. gradual typing e.g. (Typed Clojure) clojure.specclojure.spec contract system core.typed
  25. 25. Common mistakes with maps ... ;; typo in key name geometry.sphere=> (surface-area #::{:radias 2}) 0 ;; incorrect value type geometry.sphere=> (volume #::{:radius "2"}) 33.510321638291124
  26. 26. Introduce clojure.spec geometry.sphere=> (require '[cljs.spec.alpha :as s #_=> :include-macros true]) nil geometry.sphere=> (s/def ::radius (s/and number? pos?)) :geometry.sphere/radius geometry.sphere=> (s/def ::sphere (s/keys :req [::radius])) :geometry.sphere/sphere geometry.sphere=> (s/fdef surface-area #_=> :args (s/cat :sphere ::sphere) #_=> :ret number?) geometry.sphere/surface-area geometry.sphere=> (s/fdef volume #_=> :args (s/cat :sphere ::sphere) #_=> :ret number?) geometry.sphere/volume
  27. 27. Instrument specs ※ add as a dependency (cf. ) geometry.sphere=> (require '[cljs.spec.test.alpha :as stest #_=> :include-macros true]) nil geometry.sphere=> (stest/instrument) [geometry.sphere/surface-area geometry.sphere/volume] test.check CLJS-1792 # for example $ lumo -c src:~/.m2/repository/org/clojure/test.check-0.9.0.jar
  28. 28. Spec-instrumented surface­area function geometry.sphere=> (surface-area #::{:radius 2}) 50.26548245743669 geometry.sphere=> (surface-area #::{:radias 2}) Call to #'geometry.sphere/surface-area did not conform to spec: In: [0] val: #:geometry.sphere{:radias 2} fails spec: :geometry.sphere/sphere at: [:args :sphere] predicate: (contains? % :geometry.sphere/radius) :cljs.spec.alpha/spec #object[cljs.spec.alpha.t_cljs$spec$alpha 10508] :cljs.spec.alpha/value (#:geometry.sphere{:radias 2}) :cljs.spec.alpha/args (#:geometry.sphere{:radias 2}) :cljs.spec.alpha/failure :instrument ,,,
  29. 29. Spec-instrumented volume function geometry.sphere=> (volume #::{:radius 2}) 33.510321638291124 geometry.sphere=> (volume #::{:radius "2"}) Call to #'geometry.sphere/volume did not conform to spec: In: [0 :geometry.sphere/radius] val: "2" fails spec: :geometry.sphere/radius at: [:args :sphere :geometry.sphere/radius] predicate: number? :cljs.spec.alpha/spec #object[cljs.spec.alpha.t_cljs$spec$alpha 10508] :cljs.spec.alpha/value (#:geometry.sphere{:radius "2"}) :cljs.spec.alpha/args (#:geometry.sphere{:radius "2"}) :cljs.spec.alpha/failure :instrument ,,,
  30. 30. Land of Lisp invades JS world!!Land of Lisp invades JS world!!
  31. 31. Further ReadingFurther Reading
  32. 32. ClojureClojure Clojure o cial site 日本語版 Clojureの世界と実際のWeb開発 Clojureの世界観 ClojureでREPL駆動開発を始めよう Spectacular Future with clojure.spec
  33. 33. ClojureScriptClojureScript ClojureScript o cial site
  34. 34. Reagent/re-frameReagent/re-frame cf. Reagent Guide to Reagent re-frame Re-frame: The Guide to Building Blocks ClojureScript & ReagentでReact入門してみた ClojureScript/re-frame開発における思考フロー Elm開発における思考フロー

×