4

多くのClojure関数はさまざまな数の引数を受け入れますが、ドキュメントと、関数の使用方法との関係に少し混乱することがよくあります。

たとえば、(doc partial)これを返します。

([f arg1] [f arg1 arg2] [f arg1 arg2 arg3] [f arg1 arg2 arg3 & more])

私の質問は特に部分的なものではありませんが...

なぜ最大arg1arg2arg3以上であり、arg1以上またはarg1arg2以上またはarg1arg2 arg3 arg4 arg5 arg6 arg7 arg8以上ではないのですか?

私は最後のものに面白がっていますが、これは非常に現実的な質問です。何が&moreの前にいくつの「argX」を置く必要があるかを決定しますか?

4

2 に答える 2

7

次の答えは私の側の推測です:showusの実装を見てpartialください:

(defn partial
  "Takes a function f and fewer than the normal arguments to f, and
  returns a fn that takes a variable number of additional args. When
  called, the returned function calls f with args + additional args."
  {:added "1.0"
   :static true}
  ([f arg1]
   (fn [& args] (apply f arg1 args)))
  ([f arg1 arg2]
   (fn [& args] (apply f arg1 arg2 args)))
  ([f arg1 arg2 arg3]
   (fn [& args] (apply f arg1 arg2 arg3 args)))
  ([f arg1 arg2 arg3 & more]
   (fn [& args] (apply f arg1 arg2 arg3 (concat more args)))))

ご覧のとおり、partialを呼び出すたびに同じことが行われます。つまり、いくつかの引数を受け入れる関数を返し、apply入力引数と新しい引数を使用して入力関数を呼び出します。したがって、これは確かにとして記述されている可能性がありますarg1 & more。しかし、待ってください。applyの実装も見てみましょう。

(defn apply
 "Applies fn f to the argument list formed by prepending intervening arguments to args."
 {:added "1.0"
  :static true}
 ([^clojure.lang.IFn f args]
    (. f (applyTo (seq args))))
 ([^clojure.lang.IFn f x args]
    (. f (applyTo (list* x args))))
 ([^clojure.lang.IFn f x y args]
    (. f (applyTo (list* x y args))))
 ([^clojure.lang.IFn f x y z args]
    (. f (applyTo (list* x y z args))))
 ([^clojure.lang.IFn f a b c d & args]
    (. f (applyTo (cons a (cons b (cons c (cons d (spread args)))))))))

Applyはコア関数であり、引数の数が異なると実行方法も異なります。これは、パフォーマンス上の理由から適用するための最適化です。これが、部分的な(および他のそのような関数)のさまざまなアリティを公開する理由です。これは、コードの内部実行がさまざまなアリティで異なるためです。

clojure /コアチームは、arg1 arg2 arg3以上を超えて部分的なアリティを公開すること(つまり、arg1 arg2 arg3 arg4以上を書くこと)は美的ではないと考えたので、3arg以上で停止することにしました。

于 2012-05-26T19:33:41.103 に答える
3

あなたが合理的だと思うものは何でも。可変アリティでない場合は関数の呼び出しが速くなるため、制限を超えない場合に直接呼び出される関数がいくつか提供されます。

関数のIFnには20(?)引数の制限もあると思いますが、コンパイラーにそのための回避策があるかどうかはわかりません。

于 2012-05-26T19:37:22.573 に答える