1

I want to "update" a map through multiple calls of functions, in Clojure. The idea is expressed as below:

(defn foo1
  [a-map]
  (assoc a-map :key1 "value1"))

(defn foo2
  [a-map]
  (assoc a-map :key2 "value2"))

(defn foo3
  [a-map]
  (assoc a-map :key3 "value3"))

(defn -main
  []
  (let [a-map {}]
    (do (foo1 a-map)
        (foo2 a-map)
        (foo3 a-map)
        a-map)))

Apparently this piece of code is wrong because the a-map is not updated outside the scope of subroutines. It's written like this simply because it's clearer as compared to my current "correct" implementation. The expected result is:

{:key1 "value1" :key2 "value2" :key3 "value3"}

My question is, what is the best way to fulfil the task in the clojure way.

I have considered nesting a few let expressions where each let can hold the result of the updated a-map. I also considered using a loop-recur structure where the a-map is passed as a binding. But both approaches look untidy.

Any advice would be appreciated.

Cheers

EDIT: Adding a constraint to the question. The functions foo1, foo2, foo3 actually takes more parameters than only the a-map. And some of these parameters can only be determined by processing the arguments passed to -main.

1 Answer 1

2

assoc returns the updated map so you can chain your calls using the -> threading macro:

(let [a-map (-> {} 
                foo1
                foo2
                foo3)] ...)

or you could use comp:

(let [a-map ((comp foo3 foo2 foo1) {})]...)
Sign up to request clarification or add additional context in comments.

3 Comments

Ah, you're absolutely right but actually my functions need more parameters that even cannot be determined at the beginning the chained calls. I'm editing the original post to add the constraint. Any further ideas?
My fault. That doesn't make any difference as long as subsequent function calls doesn't need to destruct results from previous calls. Thanks!
with the threading macro version I don't think you need the parens around each function. So: (let [a-map (-> {} foo1 foo2 foo3)] ...)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.