$30 off During Our Annual Pro Sale. View Details »

Clojureでわかった気になるマクロの話

Yuuki Sumida
February 28, 2015

 Clojureでわかった気になるマクロの話

Yuuki Sumida

February 28, 2015
Tweet

More Decks by Yuuki Sumida

Other Decks in Technology

Transcript

  1. Clojureでわかった気になる マクロの話 2015/2/28(Sat) jvmlang.daitokai 1.0.0

  2. About me @razon 天領倉敷Scala 言い出しっぺ 岡山Javaユーザ会 幹事長 合同勉強会 in 大都会岡山

    座駆動LT大会 その他諸々 #I社
  3. About me

  4. Agenda Clojureとはどんな言語か? Clojureのマクロについて

  5. Clojureとはどんな言語か?

  6. JVM上で動くLisp系の言語

  7. ((((((()))))))

  8. どうせ括弧地獄なんでしょ?

  9. どうせ括弧地獄なんでしょ? はい 但し、他のLispと比べるとそうでもない (+ 1 2) ;; List [1 2

    3] ;; Vector {:name "Tama" :age "ハタチ"} ;; Map #{:hoge :fuga :piyo} ;; Set
  10. そもそもLisp #とは List Processing (defmacro if-some "bindings => binding-form test

    If test is not nil, evaluates then with binding-form bound to the value of test, if not, yields else" {:added "1.6"} ([bindings then] `(if-some ~bindings ~then nil)) ([bindings then else & oldform] (assert-args (vector? bindings) "a vector for its binding" (nil? oldform) "1 or 2 forms after binding vector" (= 2 (count bindings)) "exactly 2 forms in binding vector") (let [form (bindings 0) tst (bindings 1)] `(let [temp# ~tst] (if (nil? temp#) ~else (let [~form temp#] ~then))))))
  11. Clojureを構成する「フォーム」 bool charactor keyword list map nil number set string

    symbol vector special form
  12. 関数型プログラミング (fn [n] (* n n))

  13. 環境の話 プロジェクト管理 Leiningen 依存性解決 Javaとの連携 対話環境(REPL)

  14. 環境の話 LightTable Clojureに関しては補完もそこそこいける Live Code Evaluation

  15. Clojureのマクロについて

  16. Cのマクロ #define MAX(a, b) ((a) > (b) ? (a) :

    (b)) int a = 1; printf("%d\n", MAX(a++, 2)); // ? int a = 1; printf("%d\n", ((a++) > (2) ? (a++) : (2))); // ?
  17. Clojureのマクロ (defmacro when "Evaluates test. If logical true, evaluates body

    in an implicit do." {:added "1.0"} [test & body] (list 'if test (cons 'do body))) (macroexpand-1 `(when true (print "foo") (print "bar"))) => (if true (do (clojure.core/print "foo") (clojure.core/print "bar")))
  18. マクロの展開 (defmacro when "Evaluates test. If logical true, evaluates body

    in an implicit do." {:added "1.0"} [test & body] (list 'if test (cons 'do body))) (macroexpand-1 `(when true (print "foo") (print "bar"))) => (if true (do (clojure.core/print "foo") (clojure.core/print "bar")))
  19. テンプレートっぽい書き方でマクロを書きたい (defmacro .. "form => fieldName-symbol or (instanceMethodName-symbol args*) Expands

    into a member access (.) of the first member on the first argument, followed by the next member on the result, etc. For instance: (.. System (getProperties) (get \"os.name\")) expands to: (. (. System (getProperties)) (get \"os.name\")) but is easier to write, read, and understand." {:added "1.0"} ([x form] `(. ~x ~form)) ([x form & more] `(.. (. ~x ~form) ~@more)))
  20. 構文クオート内でのlet束縛について (defmacro and "Evaluates exprs one at a time, from

    left to right. If a form returns logical false (nil or false), and returns that value and doesn't evaluate any of the other expressions, otherwise it returns the value of the last expr. (and) returns true." {:added "1.0"} ([] true) ([x] x) ([x & next] `(let [and# ~x] (if and# (and ~@next) and#)))) (macroexpand-1 `(and true true false)) => (clojure.core/let [and__16748__auto__ true] (if and__16748__auto__ (user/and true false) and__16748__auto__))
  21. で、マクロってどんなところで使うの 特殊形式が絡むもの 評価のラップ ラムダの省略

  22. さいごに マクロ・クラブのルール 1. マクロは書くな 2. それがパターンをカプセル化する唯一の方法ならば、マクロを書け 3. 同等の関数に比べて、呼び出し側が楽になるならば、マクロを書い ても構わない

  23. おしまい よいマクロ・ライフを