пусть не выполняет второе выражение в теле

Если я правильно понимаю документацию, я могу написать следующее:

(let [a 5 b 10]
  (print a)
  (print b))

Это работает, как и ожидалось, и выводит 5 и 10. Я использую этот механизм в этом фрагменте кода (полный код здесь если вам нужна дополнительная информация):

(defn create! [fields]
  (let [username (user/unique-user (:author fields))
        competition-id (:id (competition/latest))]
    (if-not (exists? (:ld_uid fields))
      (insert entries (values {
                               :ld_uid (:ld_uid fields)
                               :title (:title fields)
                               :description (:description fields)
                               :type (:type fields)
                               :user_id (:id username)
                               :competition_id competition-id})))
    (for [link (:links fields)]
      (source/create! (:id (by-ld-uid (:ld_uid fields))) (:url link) (:title link)))))

проблема в том, что выражение for не выполняется. Операторы сами по себе работают, как и ожидалось, но в приведенном выше коде выражение insert выполняется, а for нет. Я что-то контролирую? У меня нет идей, что здесь происходит :(


person Fu86    schedule 27.01.2014    source источник
comment
Выражение for ленивое. Оберните dorun или замените на doseq.   -  person A. Webb    schedule 27.01.2014


Ответы (1)


Проблема не в том, что вы думаете: Clojure for использует ленивую оценку, то есть, если вы ничего не делаете с тем, что она возвращает, цикл никогда не запускается.

Это очень полезно для длительных циклов над массивными последовательностями, которые вам даже не нужны целиком, но когда вы на самом деле пытаетесь запустить побочные эффекты, ленивые вычисления — это то, от чего вам нужно держаться подальше.

Вместо этого вы хотите использовать doseq (http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/doseq).

person Max Noel    schedule 27.01.2014
comment
Спасибо вам, это очень помогло! - person Fu86; 28.01.2014