Skip to content

Instantly share code, notes, and snippets.

@masaedw
Created November 26, 2011 06:44
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save masaedw/1395188 to your computer and use it in GitHub Desktop.
Save masaedw/1395188 to your computer and use it in GitHub Desktop.
;; ..
;; doto
;; ->>
;; ->
;; の紹介
;; Clojure にはカッコを減らしたり、
;; オブジェクト指向ライブラリとの親和性を高めるための工夫が随所に見られる。
;; そういうものの中で便利なものを4つ紹介します
;;
;; clojure.core/..
;;
;; System.getProperties().get("os.name")
;; のようなメソッドチェーンを書くときに便利
;; .. を使わない場合
(.toLowerCase
(.get
(System/getProperties)
"os.name"))
;; 入れ子怖い
;; メソッドと引数がはなればなれになる
;; 処理の順番に読めない
;; .. を使う場合
(.. System
getProperties
(get "os.name")
toLowerCase)
;; 入れ子にならない
;; メソッドと引数がセットで保たれる
;; 処理の順番に読める
;; 実際には↑のプログラムはあまりイケてない。
(.toLowerCase (System/getProperty "os.name"))
;; と書けば良い
;; 使用例
(defn getCurrentDir []
"get working directory"
(.. (java.io.File. ".")
getAbsoluteFile
getParent))
;;↑これもあまりイケてない
(System/getProperty "user.dir")
;; と書ける
;;
;; clojure.core/doto
;;
;; JPanel panel = new MyPanel();
;; panel.setFocusable(focusable);
;; panel.setForeground(fgcolor);
;; panel.setBackground(bgcolor);
;; panel.addKeyListener(panel);
;; panel.addConpomentListener(panel);
;;
;; のようなことを書くときに便利
;; doto を使わない場合
(let [h (java.util.HashMap.)]
(.put h "a" 1)
(.put h "b" 2)
(.put h "c" 3)
h)
;; 一時変数に名前をつける必要がある
;; 第二引数に一時変数が来る同じパターンの繰り返し
;; 最後に値を返す必要がある
;; 値を返さない式が並んでいる……副作用怖い……
;; doto を使う場合
(doto (new java.util.HashMap)
(.put "a" 1)
(.put "b" 2)
(.put "c" 3))
;; 第二引数に同じものが来るパターンを抽象化する
;; 一時変数に名前をつけなくて良い
;; 第一引数が値として返る
;; "do" が副作用のマーカーになる
;;
;; clojure.core/->>
;;
;; 関数呼出の入れ子を(処理の積み重ね)を平坦化する
;;
;; (cons 'd (cons 'c (cons 'b (cons 'a ())))
;;
;; のような、最後の引数に前の処理の結果が来るパターン
;;
(cons 'd (cons 'c (cons 'b (cons 'a ()))))
(->> ()
(cons 'a)
(cons 'b)
(cons 'c)
(cons 'd))
;;
;; clojure.core/->
;;
;; 関数呼出の入れ子を平坦化する
;; (conj (conj (conj (conj () 'a) 'b) 'c) 'd)
;; のような、第一引数に前の処理の結果が来るパターン
(conj (conj (conj (conj () 'a) 'b) 'c) 'd)
(-> ()
(conj 'a)
(conj 'b)
(conj 'c)
(conj 'd))
;; doto と似ているが、dotoでは結果が捨てられるのに対して、
;; -> は 前の処理の結果が次の処理に渡るところが違う
;; ところで、4clojure をやっていると無名関数をよく作る羽目になる
;; -> と ->> はよく使うんだけど、最初の引数をパラメータ化して関数として使うことが多い
;; 関数を返すバージョンをデフォルトで用意しておいて欲しい
;; 実装例
(defmacro => [& body]
"same as #(-> % body ...)"
`(fn [arg#]
(-> arg# ~@body)))
(defmacro =>> [& body]
"same as #(->> % body ...)"
`(fn [arg#]
(->> arg# ~@body)))
;; 作ってみたけど実プログラムではあまり使いどころがなかった
;; こんなゴルフのためだけのマクロなんてデフォルトで入ってなくて良かったです
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment