Как я должен повторить последовательность? - PullRequest
3 голосов
/ 14 июля 2011

Ниже моя попытка повторить последовательность карт; код не выполняется из-за ошибки приведения: 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 ]

5 голосов
/ 14 июля 2011

Вы завернули 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 и do вокруг for должны звонить в колокол, чтобы что-то можно было улучшить. И действительно, 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 голос
/ 14 июля 2011

ОК, похоже, вы пытаетесь выполнить запрос к базе данных из Clojure. Например, вам может потребоваться предоставить дополнительную информацию о таблице «users» и о том, как выглядит ваш набор результатов запроса.

В любом случае, что-то вроде этого может работать

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

(map #(:category %) a)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...