回答:
シグネチャのアリティが異なる場合、関数は複数のシグネチャを持つことができます。これを使用して、デフォルト値を指定できます。
(defn string->integer
([s] (string->integer s 10))
([s base] (Integer/parseInt s base)))
と仮定するfalse
とnil
、両方とも非値と見なされ、(if (nil? base) 10 base)
に短縮される(if base base 10)
か、さらにに短縮される可能性があることに注意してください(or base 10)
。
recur
同じアリティでしか機能しないようです。上記を再試行した場合の例:java.lang.IllegalArgumentException: Mismatched argument count to recur, expected: 1 args, got: 2, compiling:
(string->integer s 10)
ますか?
rest
Clojure 1.2 [ ref ] 以降、引数をマップとして分解することもできます。これにより、関数の引数に名前を付けてデフォルトを提供できます。
(defn string->integer [s & {:keys [base] :or {base 10}}]
(Integer/parseInt s base))
今すぐ電話できます
(string->integer "11")
=> 11
または
(string->integer "11" :base 8)
=> 9
ここでこれを実際に見ることができます:https : //github.com/Raynes/clavatar/blob/master/src/clavatar/core.clj(例)
このソリューションは元のソリューションの精神に近いですが、ややクリーンです
(defn string->integer [str & [base]]
(Integer/parseInt str (or base 10)))
同様のパターン便利使用することができるor
と組み合わせますlet
(defn string->integer [str & [base]]
(let [base (or base 10)]
(Integer/parseInt str base)))
この場合はより詳細ですが、デフォルトを他の入力値に依存させる場合に便利です。たとえば、次の関数について考えます。
(defn exemplar [a & [b c]]
(let [b (or b 5)
c (or c (* 7 b))]
;; or whatever yer actual code might be...
(println a b c)))
(exemplar 3) => 3 5 35
このアプローチは、名前付き引数(M. Gilliarのソリューションのように)でも機能するように簡単に拡張できます。
(defn exemplar [a & {:keys [b c]}]
(let [b (or b 5)
c (or c (* 7 b))]
(println a b c)))
または、さらにフュージョンを使用する:
(defn exemplar [a & {:keys [b c] :or {b 5}}]
(let [c (or c (* 7 b))]
(println a b c)))
or
or
異なっている:or
ので、or
の違いを知らないnil
とfalse
。
検討する必要があると思われる別のアプローチがあります。部分関数です。これらは間違いなく、関数のデフォルト値を指定するためのより「機能的」でより柔軟な方法です。
最初に、必要に応じて、主要パラメータとしてデフォルトとして提供するパラメータを持つ関数を作成します。
(defn string->integer [base str]
(Integer/parseInt str base))
これは、Clojureのバージョンでpartial
は、「デフォルト」値を関数定義に現れる順序でのみ提供できるためです。パラメータが必要に応じて順序付けられたら、関数を使用してpartial
関数の「デフォルト」バージョンを作成できます。
(partial string->integer 10)
この関数を複数回呼び出し可能にするために、次のコマンドを使用して変数に配置できますdef
。
(def decimal (partial string->integer 10))
(decimal "10")
;10
次を使用して「ローカルデフォルト」を作成することもできますlet
。
(let [hex (partial string->integer 16)]
(* (hex "FF") (hex "AA")))
;43350
関数の部分的なアプローチには、他のものよりも1つの重要な利点があります。関数のプロデューサーではなく、関数のコンシューマーが関数の定義を変更する必要なく、デフォルト値を決定できます。これは、デフォルトの機能が私が望むものではないと決定した例で示されています。hex
decimal
このアプローチのもう1つの利点は、デフォルトの関数に、よりわかりやすい別の名前(10進数、16進数など)を割り当てたり、スコープ(var、local)を変えたりできることです。必要に応じて、部分関数を上記のアプローチのいくつかと組み合わせることができます。
(defn string->integer
([s] (string->integer s 10))
([base s] (Integer/parseInt s base)))
(def hex (partial string->integer 16))
(この応答の上部にある理由により、パラメーターの順序が逆になっているため、これはブライアンの回答とは少し異なります)
https://clojuredocs.org/clojure.core/fnilを調べることもでき(fnil)
ます
(recur s 10)
使用して、recur
代わりに関数名を繰り返しますstring->integer
。これにより、将来関数の名前を変更しやすくなります。誰かがrecur
これらの状況で使用しない理由を知っていますか?