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

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

Yuuki Sumida
February 28, 2015

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

Yuuki Sumida

February 28, 2015
Tweet

More Decks by Yuuki Sumida

Other Decks in Technology

Transcript

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

    3] ;; Vector {:name "Tama" :age "ハタチ"} ;; Map #{:hoge :fuga :piyo} ;; Set
  2. そもそも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))))))
  3. 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))); // ?
  4. 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")))
  5. マクロの展開 (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")))
  6. テンプレートっぽい書き方でマクロを書きたい (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)))
  7. 構文クオート内での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__))