如何在另一个defn中调用一个defn函数以及如何在Clojure中调试

时间:2013-11-05 03:26:56

标签: clojure

我在使用Clojure运行程序时遇到问题。我几周前就开始学习Clojure了。所以我不知道调试Clojure程序的快捷方法。我的func2在(adj(a b))处引发了一个异常,如下所示:

  

ClassCastException java.lang.Long无法强制转换为clojure.lang.IFn   用户/ FUNC2。

我不知道它有什么问题。有人能用我的编码指出问题吗? 在func3中,我以递归方式调用func2,但它会抛出:

  

ArityException传递给:PersistentVector的args(0)错误的数量   clojure.lan g.AFn.throwArity(AFn.java:437)

func3有什么问题?谢谢。

(defn adj [value1 value2]
    (def result (+ (/ value1 2) (/ value2 2)))  
    (if (= (mod result 2) 1)
        (+ result 1)
        result
    )
)

(defn func2 [list]
    (let [[a b c d] list] 
        (inc d)
        ([(adj c a) (adj a b) (adj b c) d]))    
)

(defn func3 [list]
    (loop [v list r []]

    (if(= (v 0) (v 1) (v 2))
        (conj list r)               
        (func3(func2(list)))
    ))
)

2 个答案:

答案 0 :(得分:3)

这些功能的预期结果是什么?我们可能需要看到一些样本输入和预期结果才能真正帮助您。

这是我尝试清理它们的方法。我注意到我作为评论所做的更改。 func3有一个最严重的问题,因为它是一个无限递归 - 没有结束条件。什么应该导致它停止工作并返回结果?

(defn adj [value1 value2]
   ;; don't use def within functions, use let
  (let [result (+ (/ value1 2) (/ value2 2))]
    (if (= (mod result 2) 1)
      (+ result 1)
      result)))

(defn func2 [list]
  (let [[a b c d] list]
    ;; The extra parens around this vector were causing it
    ;; to be called as a function, which I don't think is
    ;; what you intended:
    [(adj c a) (adj a b) (adj b c) d]))

;; This needs an end condition - it's an infinite recursion
(defn func3 [list]
  (loop [v list r []]
    (if (= (v 0) (v 1) (v 2))
      (conj list r)
      ;; Removed extra parens around list
      (func3 (func2 list)))))

我说不在函数中使用def的原因是总是创建一个全局函数。对于本地绑定,您需要let

关于额外的parens,[1 2 3]([1 2 3])之间的区别在于前者返回包含数字1,2和3的向量,而后者尝试将该向量称为函数。 func2中的文字向量和list中的func3周围有过多的parens,导致异常。

作为样式注释,名称list不是一个好选择。一方面,它正在影响clojure.core/list,另一方面,你可能正在使用向量而不是列表。使用coll(用于收集)或s(用于序列)作为名称更为惯用。

这表明至少还有一个其他变化。在func3中,您使用仅向量的特征(使用向量作为函数来按索引执行查找),因此为了更通用(接受其他数据结构),您可以转换为具有vec的向量:

(defn func3 [coll]
  (loop [v (vec coll) r []]
    (if (= (v 0) (v 1) (v 2))
      (conj v r)
      (func3 (func2 v)))))

答案 1 :(得分:0)

哦,没有必要调试它。我建议你看一下LightTable。

前两个功能很容易修复:

(defn adj [value1 value2]
  ;(def result (+ (/ value1 2) (/ value2 2))) def creates a global binding in current namespace !!!  
  (let [result (+ (/ value1 2) (/ value2 2))]  
  (if 
    (= (mod result 2) 1)
    (inc result)
    result)))

(defn func2 [xx]
  (let [[a b c d] xx] 
    [ (adj c a) (adj a b) (adj b c) (inc d)]
    ))

第三个功能对我来说并不清楚。我没有读你的意图。我理解的是:“继续将func2应用到自身,直到其结果的前三个元素相等。”但我担心这种情况永远不会得到满足,所以我用一个真实的替换它,以便只看到一个结果而不会吹掉堆栈。

(defn func3 [xx]
  (loop [ v (func2 xx) ]
    (if
      ;(= (v 0) (v 1) (v 2))
      true
      v               
      (recur (func2 v))
    )))

有用的链接:http://clojure.org/cheatsheet

干杯 -