clojure - 函数让变量不可变

时间:2017-11-01 21:27:27

标签: clojure

您好我在尝试运行我的clojure程序时收到运行时错误消息。

引起:java.lang.IllegalArgumentException:无法分配给非变量:x

请让我知道我对可变变量的理解,以便解决此代码问题。提前谢谢。

(defn gcd [a b]
  (if (zero? b)
    a
    (recur b (mod a b))
  )
)

(defn euler_phi [n]
  (let [x 0]
    (loop [idx_i 1]
      (when (= 1 (gcd idx_i n))
        (set! x (inc x))
        (print " * ")
      )
      (when (< idx_i n)
        (recur (inc idx_i))
      )
    )
    x
  )
)

2 个答案:

答案 0 :(得分:2)

set! Doc 你不能分配功能参数 或本地绑定。只有Java字段,Vars,Refs和Agents是可变的 Clojure的。有关详细信息,请参阅http://clojure.org/special_forms

答案 1 :(得分:0)

如果你想在Clojure中编写命令式代码,只需使用atom任何你将使用Java变量的地方:

(ns tst.demo.core
  (:use demo.core ) )

(defn gcd [a b]
  (if (zero? b)
    a
    (recur b (mod a b))))

(defn euler-phi [n]
  (let [x (atom 0)]
    (loop [idx 1]
      (when (= 1 (gcd idx n))
        (swap! x inc)
        (print " * "))
      (when (< idx n)
        (recur (inc idx))))
    @x))

(dotimes [n 30]
  (print "n:" n "   ")
  (let [result (euler-phi n)]
    (println "    result=" result)))

结果:

n: 0     *     result= 1
n: 1     *     result= 1
n: 2     *     result= 1
n: 3     *  *     result= 2
n: 4     *  *     result= 2
n: 5     *  *  *  *     result= 4
n: 6     *  *     result= 2
n: 7     *  *  *  *  *  *     result= 6
n: 8     *  *  *  *     result= 4
n: 9     *  *  *  *  *  *     result= 6
n: 10     *  *  *  *     result= 4
n: 11     *  *  *  *  *  *  *  *  *  *     result= 10
n: 12     *  *  *  *     result= 4
n: 13     *  *  *  *  *  *  *  *  *  *  *  *     result= 12
n: 14     *  *  *  *  *  *     result= 6
n: 15     *  *  *  *  *  *  *  *     result= 8
n: 16     *  *  *  *  *  *  *  *     result= 8
n: 17     *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *     result= 16
n: 18     *  *  *  *  *  *     result= 6
n: 19     *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *     result= 18
n: 20     *  *  *  *  *  *  *  *     result= 8
n: 21     *  *  *  *  *  *  *  *  *  *  *  *     result= 12
n: 22     *  *  *  *  *  *  *  *  *  *     result= 10
n: 23     *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *     result= 22
n: 24     *  *  *  *  *  *  *  *     result= 8
n: 25     *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *     result= 20
n: 26     *  *  *  *  *  *  *  *  *  *  *  *     result= 12
n: 27     *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *     result= 18
n: 28     *  *  *  *  *  *  *  *  *  *  *  *     result= 12
n: 29     *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *     result= 28

以下是代码的更多功能版本:

(ns tst.demo.core
  (:use demo.core tupelo.test )
  (:require [tupelo.core :as t] ))
(t/refer-tupelo)

(defn gcd [a b]
  (if (zero? b)
    a
    (recur b (mod a b))))

(defn euler-phi [n]
  (apply +
    (t/forv [idx (t/thru 1 n)]
      (if (= 1 (gcd idx n))
        1
        0))))

(dotimes [n 30]
  (println "n:" n "    result=" (euler-phi n)))

结果:

n: 0     result= 0
n: 1     result= 1
n: 2     result= 1
n: 3     result= 2
n: 4     result= 2
n: 5     result= 4
n: 6     result= 2
n: 7     result= 6
n: 8     result= 4
n: 9     result= 6
n: 10     result= 4
n: 11     result= 10
n: 12     result= 4
n: 13     result= 12
n: 14     result= 6
n: 15     result= 8
n: 16     result= 8
n: 17     result= 16
n: 18     result= 6
n: 19     result= 18
n: 20     result= 8
n: 21     result= 12
n: 22     result= 10
n: 23     result= 22
n: 24     result= 8
n: 25     result= 20
n: 26     result= 12
n: 27     result= 18
n: 28     result= 12
n: 29     result= 28

请注意,n = 0的结果是不同的.....我没有尝试调试它。