Created
November 26, 2011 06:44
-
-
Save masaedw/1395188 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; .. | |
;; 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