f00860
f00860

Reputation: 3576

let does not execute the second expression in the body

If I understand the documentation right, I can write this:

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

This works as expected and prints out 5 and 10. I use this mechanism in this code snippet (The full code is here if you need more reference):

(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)))))

the problem is, the for expression is not executed. The statements as its own works as expected but in this code above the insert expression is executed but the for not. Do I oversee something? I am out of ideas whats going wrong here :(

Upvotes: 2

Views: 111

Answers (1)

Max Noel
Max Noel

Reputation: 8910

The problem is not what you think: Clojure's for uses lazy evaluation -- that is, if you don't do anything with what it returns, the loop never runs.

That's very useful for long-running loops over massive sequences that you don't even need in their entirety, but when you're actually trying to run side effects, lazy evaluation is something you need to stay away from.

You want to use doseq instead (http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/doseq).

Upvotes: 8

Related Questions