あなたは 2 つの質問をしていますが、私はそれらに逆の順序で答えようとします。
コレクションを引数として適用する
コレクションを関数の引数として使用するには、各項目が関数の位置引数であるため、関数を使用しapply
ます。
(apply sum-of-squares greats) ;; => 25
可読性
読みやすさに関するより一般的な質問については、次のとおりです。
問題を一般化することで、読みやすくすることができます。あなたのコード サンプルから、問題はコレクション内の 2 つの最大数に対して平方和を実行することで構成されているように見えます。sort
したがって、最初の 2 つの項目を取得して降順でコレクションに視覚的にわかりやすくなります。
(defn greater [& numbers]
(take 2 (sort > numbers)))
(defn sum-of-squares [x y]
(+ (* x x) (* y y)))
その後、 を使用apply
してそれらを関数に渡すことができますsum-of-squares
。
(apply sum-of-squares (greater 2 3 4)) ;; => 25
心に留めておいてください: sort 関数は遅延ではありません。したがって、与えられたコレクション全体を認識し、並べ替えます。これは、一部のシナリオでパフォーマンスに影響を与える可能性があります。しかし、この場合、それは問題ではありません。
一歩先へ
sum-of-squares
2 つの引数x
とy
をコレクションに切り替えることで、複数の引数を処理するように関数をさらに一般化できます。
(defn sum-of-squares [& xs]
(reduce + (map #(* % %) xs)))
#()
上記の関数は、省略形の構文を使用して数値を 2 乗する無名関数を作成します。その関数は、コレクションmap
内のすべてのアイテムに対してを使用して遅延マッピングされます。xs
だから、[1 2 3]
なるでしょう(1 4 9)
。このreduce
関数は各アイテムを受け取り、そのアイテムと+
現在の合計に関数を適用して、コレクションの合計を生成します。(+
は複数のパラメーターを取るため、この場合は も使用できますapply
。)
スレッド化マクロの 1 つを使用してすべてをまとめると、->>
非常に親しみやすくなります。(ただし、この場合、より読みやすくするためにある程度の構成可能性をトレードオフしたという議論がなされる可能性があります。)
(defn super-sum-of-squares [n numbers]
(->> (sort > numbers)
(take n)
(map #(* % %))
(reduce +)))
(super-sum-of-squares 2 [2 3 4]) ;;=> 25