Getting Clojure 5章 その他の関数
同じ関数名で、引数異なるやつとかやりたい
code: overload.clj
user=> (defn greet
リスト引数
(defn foo [x & args] x)
& argsというアンバサンドの次の引数がリスト引数になる
それより前のが固定引数
MultiMethod
(defmulti <method名> <keywordを返す関数>
(defmethod <上で定義したmultimethod名> <期待されるkeyword> [引数])
マルチメソッドは同じコードファイル内に定義されている必要もない、拡張性が高い
再帰サポート
再帰関数内で、再帰関数を普通に呼ぶと深さによってはスタックオーバーフロー起こす(4000くらいで起きるらしい)
clojureでは、再帰専用の構文を用意している そのまんまだけど recur
使い方は簡単で、再帰内で元々再帰関数名を呼び出していたところをrecurに置き換えるだけ
再帰では、2つの引数パターンを用意しないといけないのが手間になりやすい
例えば、reduceっぽい処理するときに呼び出し側は初期値意識しなくてもいいように引数1つで呼べるけど、再帰するときは、内部で引数2つ(残り配列と現在の合計値みたいな)用意しないといけないとか
loop
束縛構文らしい、recur限定?かはちょっとまだわからない
(loop [arity1 <束縛したい値1> arity2 <束縛したい値2>])みたいな使い方
recurはかなり低レベルのツール、もっと便利なやつあるよ(applyとからしい)
Docstrings
;; 通常のコメントに加えてfunction定義直後に文字列を与えると、それはdocstringとして動作する
code: docstring.clj
(defn foo
"this is docstring"
...)
docstringで定義した場合は、REPLでdocmacroを使って確認できるよ
pre, post condition
functionの実行前に実行に値する引数かのチェックや、返り値の型チェックを行い異常時は例外を投げたい場合の簡易構文
functionの引数定義後にmap形式で、:pre, :postをキーとするを渡してあげる
code: pre-post-condition.clj
...
)
multiarityとかの注意点
引数の数が重複するような定義はできないこと
code: これはエラー.clj
(defn one-two-or-more
(a (println "One arg:" a)) (a b (println "Two args:" a b)) (more (println "More than two:" more)))
可変長引数とかぶってしまっているのでだめ