括弧が間違っているようです。フォームif
が必要else
です。次のような意味だったと思います。
(defn addall
([] 0)
([& x]
(if (empty? x)
0 ;;; <=== no ')' after 0
(+ (first x) (addall (rest x)))))) ;;; <== extra ')' here
しかし、それが修正されたとしても、コードはまだ間違っています。複数の引数で呼び出されると想定しています -- (addall 1 2 3)
-- しかし、それ自体にリストを渡すことで再帰します -- (addall [2 3])
。これにより、進行しないループに陥ってしまいます。これは、次のprint
ステートメントを追加することで確認できます。
(defn addall
([] 0)
([& x]
(print (str "new x: " x "\n"))
(if (empty? x)
0 ;;; <=== no ')' after 0
(+ (first x) (addall (rest x))))))
これにより、実際にコンピューターでセグメンテーション違反が発生しました。
また、2 つの基本ケースがあります。代わりにこれをお勧めします:
(defn addall
[xs]
(if (empty? xs)
0
(+ (first xs)
(addall (rest xs)))))
ベクトルで呼び出すには:
(addall [1 2 3])
または、可変引数関数を使用する場合は、次も必要ですapply
。
(defn addall
[& x]
(print (str "new x: " x "\n"))
(if (empty? x)
0
(+ (first x)
(apply addall (rest x))))) ;;; <=== apply addall
とはいえ、Clojure には末尾呼び出しの最適化がないことに注意してください。つまり、このコードは中規模の入力では失敗します。Clojure ではloop/recur
、組み込みのシーケンス処理関数の使用を推奨しています。