Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Practical REPL-driven Development with Clojure

Practical REPL-driven Development with Clojure

Enjoy REPL-driven development with Clojure! (*> ᴗ •*)ゞ

Kent OHASHI

October 13, 2017
Tweet

More Decks by Kent OHASHI

Other Decks in Programming

Transcript

  1. Self-introduction /laʒenɔʁɛ̃k/ カマイルカ lagé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])
  2. Contents 1. Clojure Quick Intro 2. Leiningen 3. Clojure REPL

    4. Lisp Editing 5. REPL-driven Development in Practice
  3. Clojure Lisp S-expressions, macros, etc. REPL-driven development functional programming language

    dynamic language JVM language (cf. ClojureScript) ⇒ simple and powerful language
  4. literals type example string "abc" character \a number 1, 2.0,

    3N, 4.5M, 6/7, 8r10 boolean true, false nil nil keyword :a, :user/a, ::a, ::x/a symbol 'a, 'user/a, `a, `x/a
  5. type example list '(1 2 3), '(+ 1 2 3)

    vector [1 2 3] set #{1 2 3} map {:a 1 :b 2}, #:user{:a 1 :b 2}, #::{:a 1 :b 2}, #::x{:a 1 :b 2} function (fn [x] (* x x))
  6. lein repl starts Clojure REPL $ lein repl nREPL server

    started on port 49482 on host 127.0.0.1 - nrepl://1 27.0.0.1:49482 REPL-y 0.3.7, nREPL 0.2.12 Clojure 1.8.0 Java HotSpot(TM) 64-Bit Server VM 1.8.0_121-b13 Docs: (doc function-name-here) (find-doc "part-of-name-here") Source: (source function-name-here) Javadoc: (javadoc java-object-or-class-here) Exit: Control+D or (exit) or (quit) Results: Stored in vars *1, *2, *3, an exception in *e user=>
  7. lein new generates a new Clojure project generate a project

    with app template cf. $ lein new app clj-demo Generating a project called clj-demo based on the 'app' template lein-template
  8. $ tree clj-demo/ clj-demo/ ├── CHANGELOG.md ├── LICENSE ├── README.md

    ├── doc │ └── intro.md ├── project.clj ├── resources ├── src │ └── clj_demo │ └── core.clj └── test └── clj_demo └── core_test.clj
  9. cf. src/clj_demo/core.clj (ns clj-demo.core (:gen-class)) (defn -main "I don't do

    a whole lot ... yet." [& args] (println "Hello, World!"))
  10. lein test runs tests $ lein test lein test clj-demo.core-test

    lein test :only clj-demo.core-test/a-test FAIL in (a-test) (core_test.clj:7) FIXME, I fail. expected: (= 0 1) actual: (not (= 0 1)) Ran 1 tests containing 1 assertions. 1 failures, 0 errors. Tests failed.
  11. lein uberjar creates jar files $ lein uberjar Compiling clj-demo.core

    Created /Users/k.ohashi/code/clj-demo/target/uberjar/clj-demo-0. 1.0-SNAPSHOT.jar Created /Users/k.ohashi/code/clj-demo/target/uberjar/clj-demo-0. 1.0-SNAPSHOT-standalone.jar $ java -jar target/uberjar/clj-demo-0.1.0-SNAPSHOT-standalone.ja r Hello, World!
  12. evaluate expressions clj-demo.core=> (map inc [0 1 2]) (1 2

    3) clj-demo.core=> (println (map inc [0 1 2])) (1 2 3) nil
  13. clojure.repl/doc prints documentation clj-demo.core=> (doc map) ------------------------- clojure.core/map ([f] [f

    coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]) Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments. Returns a transducer when no collection is provided. nil
  14. clojure.repl/source prints source code clj-demo.core=> (source map) (defn map "Returns

    a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments. Returns a transducer when no collection is provided." {:added "1.0" :static true} ([f] (fn [rf] (fn ([] (rf)) ([result] (rf result)) ([result input] (rf result (f input))) ([result input & inputs] (rf result (apply f input inputs))))))
  15. clojure.core/*1, *2, *3 special vars bound to the most recent

    values printed clj-demo.core=> 21 21 clj-demo.core=> 2 2 clj-demo.core=> (* *2 *1) 42
  16. clojure.core/*e special var bound to the most recent exception caught

    by the REPL clj-demo.core=> (+ 1 "2") ClassCastException java.lang.String cannot be cast to java.lang.Number clj-demo.core=> *e #error { :cause "java.lang.String cannot be cast to java.lang.Number" :via [{:type java.lang.ClassCastException :message "java.lang.String cannot be cast to java.lang.Number" :at [clojure.lang.Numbers add "Numbers.java" 128]}] :trace [[clojure.lang.Numbers add "Numbers.java" 128] [clojure.lang.Numbers add "Numbers.java" 3640] [clj_demo.core$eval1328 invokeStatic "form-init3161334546666357405.cl [clj_demo.core$eval1328 invoke "form-init3161334546666357405.clj" 1] [clojure.lang.Compiler eval "Compiler.java" 6927] [clojure.lang.Compiler eval "Compiler.java" 6890] [clojure.core$eval invokeStatic "core.clj" 3105]
  17. (

  18. (

  19. (

  20. (

  21. (

  22. (

  23. )

  24. (

  25. ) )

  26. ) )

  27. Clone the repository $ git clone git://github.com/functional-koans/clojure-koans.git Cloning into 'clojure-koans'...

    remote: Counting objects: 1590, done. remote: Compressing objects: 100% (7/7), done. remote: Total 1590 (delta 2), reused 4 (delta 1), pack-reused 15 80 Receiving objects: 100% (1590/1590), 269.87 KiB | 651.00 KiB/s, done. Resolving deltas: 100% (755/755), done.
  28. Run koans $ cd clojure-koans/ $ lein koan run Starting

    auto-runner... Considering /Users/k.ohashi/code/clojure-koans/src/koans/01_equa lities.clj... Now meditate upon /Users/k.ohashi/code/clojure-koans/src/koans/0 1_equalities.clj --------------------- Assertion failed! clojure.lang.ExceptionInfo: We shall contemplate truth by testin g reality, via equality (= __ true) {:line 6}, compiling:(/Users/k.ohashi/code/clojure-k oans/src/koans/01_equalities.clj:4:1)
  29. Save changes and check the meditation result ... Now meditate

    upon /Users/k.ohashi/code/clojure-koans/src/koans/0 1_equalities.clj --------------------- Assertion failed! clojure.lang.ExceptionInfo: You can test equality of many things (= (+ 3 4) 7 (+ 2 __)) {:line 12}, compiling:(/Users/k.ohashi/co de/clojure-koans/src/koans/01_equalities.clj:4:1)
  30. Open a new buffer with your favourite editor $ emacs

    clj-demo/src/clj_demo/4clojure/problem22.clj
  31. e.g. Count a Sequence Problem #22 Write a function which

    returns the total number of elements in a sequence. (= (__ '(1 2 3 3 1)) 5) (= (__ "Hello World") 11) (= (__ [[1 2] [3 4] [5 6]]) 3) (= (__ '(13)) 1) (= (__ '(:a :b :c)) 3) Special Restrictions: count
  32. Run your solution on the problem page (fn my-count [coll]

    (reduce (fn [n _] (inc n)) 0 coll))
  33. editor plugins/settings Clojure develompent Emacs cf. CIDER Clojure 初⼼者のための Emacs

    設定作りました 新: Emacs を使うモダンな Clojure 開発環境 Spacemacs Clojure layer Clojure development with Spacemacs & Cider
  34. IntelliJ IDEA Atom Cursive IntelliJ IDEA と Cursive で始める —

    Clojure の⽇ 本語ガイド Atom Clojure Setup ClojureやりたいけどEmacsは厳しい⼈のための proto-repl⼊⾨
  35. Lisp editing Parinfer ParEdit ParEdit チュートリアル Paredit Cheatsheet The Animated

    Guide to Paredit Lispってどう書くの? - Qiita Smartparens