我该如何迭代序列?

时间:2011-07-14 01:53:17

标签: clojure

下面是我尝试迭代一系列地图;由于转换错误导致代码失败:Exception in thread "main" java.lang.RuntimeException: java.lang.ClassCastException: clojure.lang.Cons cannot be cast to java.util.Map$Entry

任何人都可以解释/演示我应该如何迭代结果集吗?感谢。

(with-connection db
                 (with-query-results rs ["select category from users group by category"]
                                     (doall
                                       (for [s [rs]] 
                                       (do (println (val s)))))))

2 个答案:

答案 0 :(得分:5)

您将rs打包到矢量中。因此s将绑定到整个序列,而不是单个映射条目。因此,当您致电val时,它不知道如何处理序列。因此例外。这应该有效:

(with-connection db
  (with-query-results rs ["select category from users group by category"]
    (doall
      (for [rec rs
            s   rec] 
        (do
          (println (val s)))))))

然而,doall周围的丑陋dofor应响铃,可以改善一些事情。实际上for用于构造另一个懒惰序列。对于您的示例中的打算,这不适用于副作用。在这种情况下,您应该使用doseq

(with-connection db
  (with-query-results rs ["select category from users group by category"]
    (doseq [rec rs
            s   rec]
      (println (val s)))))

doseq的绑定界面与for的界面相同。然而,它立即执行,因此立即实现任何副作用。如果在for的主体中放置多个表达式,则必须将其包装到do中。这提醒人们身体应该产生价值。然而,多个表达指示副作用。因此doseq将身体包裹成do。所以你可以轻松拥有多个表达式。例如:

(doall
  (for [s seq-of-maps]
    (do
      (println (key s))
      (println (val s)))))

(doseq [s seq-of-maps]
  (println (key s))
  (println (val s)))))

根据经验,你需要副作用吗?寻找以do开头的东西!

根据经验2:如果看起来很丑陋(参见上面的比较),这应该响铃。

答案 1 :(得分:1)

好的,所以听起来你正在尝试从Clojure进行数据库查询。例如,您可能必须提供有关“users”表的更多信息以及查询结果集的外观。

无论如何,像这样的东西可以工作

(def a  (with-query-results rs ["select category from users group by category"]
          (doall rs)))

(map #(:category %) a)