【问题标题】:Collection of pairs in Clojure using consClojure 中使用 cons 收集对
【发布时间】:2014-02-14 15:09:44
【问题描述】:

我在 Clojure 中基于 Eratosthenes 的 Sieve 编写了一个 Sieve 类型的函数.....并且遇到了对列表的错误:ClassCastException clojure.lang.Cons cannot be cast to java.lang.Number clojure。 lang.Numbers.remainder(Numbers.java:171)


(defn mark-true [n]
  (cons n '(true)))

(defn unmarked? [ns]
  (not (list? ns)))

(defn divides? [m n]
  (if (= (mod n m) 0)
      true
      false ))

(defn mark-divisors [n ns]
  (cond 
      (empty? ns) '()
      (and (unmarked? (first ns)) (divides? n (first ns))) 
           (cons (cons (first ns) '(false)) (mark-divisors n (rest ns)))
      :else (cons (first ns) (mark-divisors n (rest ns)))))

(defn eratosthenes [ns]
  (cond 
      (empty? ns) '()
      (unmarked? (first ns))
           (cons (mark-true (first ns)) 
                 (eratosthenes (mark-divisors (first ns) (rest ns))))
      :else (cons (first ns) (eratosthenes (rest ns)))))

;(eratosthenes (list 2 3 4 5 6))
;=> ClassCastException clojure.lang.Cons cannot be cast to java.lang.Number  clojure.lang.Numbers.remainder (Numbers.java:171)

但是,更改标记样式,放弃 cons 并改用 conj 或向量对,都解决了错误。

我仍在寻找错误的良好解释....

【问题讨论】:

  • 如果您不发布所有相关代码,您将无法获得答案。那里没有剩余的电话......显然mark-divisors不见了。
  • 你是对的 - 谢谢
  • 在某些时候分裂?函数接收 3 和 (4 false) 参数。第二个参数不能转换为数字
  • 为什么使用不同的制作方式如 (defn mark-true [n] (conj '(true) n)) 会有所作为?

标签: java clojure


【解决方案1】:

问题是list? 在使用cons 构建的序列上检查失败,如下所示:

(list? (conj () 1)) ;=> true
(list? (cons 1 ())) ; => false

您可以将呼叫list? 切换为呼叫seq?,它应该可以工作。

有关为什么会这样的详细信息,我建议阅读此答案:Clojure: cons(seq) vs. conj(list)

【讨论】:

  • 太棒了。感谢您的解决方案。有趣的清单?在阅读参考文献中没有讨论。您的示例应该包含在其中和clojuredocs.org/clojure_core/clojure.core/list_q
  • 我认为拥有 (list? (cons 1 ())) 是设计上的错误; => 错误
  • @FredAKA,您需要考虑到 Clojure 中列表和序列之间的区别。
  • 当然,不需要将其“称为”列表,并且与可以追溯到使用 cons 构建的第一个 lisps 的众所周知的抽象相冲突
猜你喜欢
  • 2011-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多