rand-strを添削してみる
オリジナル:https://bitbucket.org/fgtrjhyu/misc/src/5d4fa9455ed0/randomstring/clj
(use '[clojure.string :only (join)]) (defn- char-range [& more] (letfn [(crange [[^Character start ^Character end]] (join (map char (range (int start) (inc (int end))))))] (join (map crange more)))) (let [characters (char-range [\0 \9] [\A \Z] [\a \z] [\_ \_])] (defn rand-str [n] (join (take n (repeatedly #(rand-nth characters)))))) (println (rand-str 256))
char-rangeについていくつか補足。
- 今回は必要ない機能を省いた。
- applyを使う代わりに分配束縛を使った。
- letfnを使った形に変形した。
- 今回はLazinessがあまり役に立たないので、文字列を返すようにした。
また、charactersはdefして外部から書き換えられるようにするのが一般的だが、オリジナルが外部からの書き換えを禁じていたのでletでdefnを包む形を取った。
これはレキシカルクロージャや(Doug Hoyteが著書のタイトルに使ったように)Let Over Lambdaと呼ばれるテクニックで、char-rangeは一度だけ呼ばれる。
オリジナルはメモ化しているが、(source memoize)すればわかるように、メモ化しても関数が毎回呼ばれ、atomをderefし、マップを探す。
もちろんメモ化は時々役に立つものの、今回は適切ではないと思う。
読んだ方の参考になれば嬉しいです。