Part of function fails silently

Skip to first unread message

Egon Steiner

Aug 19, 2015, 11:00:40 AM8/19/15
to Compojure
I have a form with a text field and two file inputs, one for an image file and one for multiple geojson files.
The form gets submitted to a route that should upload the files, run a ruby script that processes the image and then send back a page.
Here's the code:

(POST "/add-resort" {params :params} (p/add-resort params))

add-resort function:
(defn add-resort [params]
  (let [{{tempfile :tempfile filename :filename} :resort-pano
         resort-geojsons :resort-geojsons
         resort-name :resort-name} params
        filepath (str "resources/public/images/panos/" resort-name "/" filename)]
    (h/save-file tempfile filepath)
    (for [geojson resort-geojsons
          :let [{tempfile :tempfile filename :filename} geojson
                filepath (str "resources/public/data/" resort-name "/" filename)]]
      (h/save-file tempfile filepath))
    (h/process-pano filepath resort-name)
    (edit-for-resort resort-name)))

helper functions:
(defn save-file [tempfile filepath]
  (io/make-parents filepath)
  (io/copy tempfile (io/file filepath)))

(defn process-pano [filepath resort-name]
  (println (sh "ruby" (absolute-path (io/resource "tiler.rb"))
             (absolute-path filepath)
             (absolute-path (str "resources/public/images/panos/" resort-name "/"))

When the code is like this the upload of the geojson files fails.
If I remove the last two lines of add-resort it works as expected.
Can anyone tell me what I'm doing wrong?

Cedric Roussel

Aug 19, 2015, 1:14:03 PM8/19/15
to Compojure
May be replace the for function with doseq, because save-file is side-effect and for is lazy

James Reeves

Aug 19, 2015, 1:16:23 PM8/19/15
to Compojure
What does edit-for-resort return?

- James

You received this message because you are subscribed to the Google Groups "Compojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to
To post to this group, send email to
Visit this group at
For more options, visit

James Reeves

Aug 19, 2015, 1:18:13 PM8/19/15
to Compojure
I think Cedric might have the answer. If the last form is the "for", then the seq it returns will be resolved as the response body. As it stands, you're creating a lazy seq and doing nothing with it.

- James

Egon Steiner

Aug 20, 2015, 2:39:04 AM8/20/15
to Compojure
Thanks that did it.
But could you explain what you mean by save-file is side-effect?
I'm still new to Clojure and Compojure.

Cedric Roussel

Aug 20, 2015, 5:11:01 AM8/20/15
to Compojure
Saving a file to disk or calling a ruby script, or printing to a log, are all called side effects because they affect the world, outside the scope of the function itself.
The return value of a function is the last form inside your function definition, anything you write before the last form is either useless or performing side-effect.
A pure function is one that have no side-effect. When you call a pure function, it's only to get it's return value and nothing more.

Here is a minimal example from that shows how lazy sequence and side-effect works together.

;; Nothing is printed because map returns a lazy-seq
user=> (def foo (map println [1 2 3]))

;; doall forces the seq to be realized
user=> (def foo (doall (map println [1 2 3])))

This is the same that happens with your code.
Might look likes it fails, but it does not, it just don't run.

Lazyness is great once you are used to it.
;;can define infinite sequence of number
(def infinite (map inc (range)))
;;forcing with doall would fill all my RAM, but may be I only need two
(take 2 infinite)

If that's still unclear, the clojure google group might be a better place to ask

Egon Steiner

Aug 20, 2015, 6:20:10 AM8/20/15
to Compojure
Thanks, I think I get it now and my function now works as I expected it.
Reply all
Reply to author
0 new messages