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し、マップを探す。

もちろんメモ化は時々役に立つものの、今回は適切ではないと思う。

読んだ方の参考になれば嬉しいです。