Education‎ > ‎Closer to Clojure‎ > ‎

Closer to Clojure 05: Loop

It is natural that Clojure does not have loop. Though Clojure does not optimise tail recursion due to limit of JVM, it introduces a similar syntax of Scheme's named let. This syntax doesn't consume stacks too much.

user=> (defn my-zipmap [keys vals]
  (loop [my-map {}
      my-keys (seq keys)
      my-vals (seq vals)]
    (if (and my-keys my-vals)
      (recur (assoc my-map (first my-keys) (first my-vals))
        (rest my-keys)
        (rest my-vals))
      my-map)))
user=> (my-zipmap [:a :b :c] [1 2 3])
{:b 2, :c 3, :a 1}

Factorial can be defined as follows.

(defn factorial [n]
  (loop [cnt n
      acc 1]
    (if (zero? cnt)
      acc
      (recur (dec cnt) (* acc cnt)))))

References:
http://clojure.org/functional_programming
http://clojure.org/special_forms#recur
当然ながら,言語コアにループはありません.ClojureはJVMを使うため末尾再帰の最適化を行えませんが,Schemeの名前付きletに似た構文を導入しています.この構文を使えばスタックを無駄に消費しません.

user=> (defn my-zipmap [keys vals]
  (loop [my-map {}
      my-keys (seq keys)
      my-vals (seq vals)]
    (if (and my-keys my-vals)
      (recur (assoc my-map (first my-keys) (first my-vals))
        (rest my-keys)
        (rest my-vals))
      my-map)))
user=> (my-zipmap [:a :b :c] [1 2 3])
{:b 2, :c 3, :a 1}

階乗は次のように書けます.

(defn factorial [n]
  (loop [cnt n
      acc 1]
    (if (zero? cnt)
      acc
      (recur (dec cnt) (* acc cnt)))))

参考
http://clojure.org/functional_programming
http://clojure.org/special_forms#recur
Comments