2

Chapter 5, Exercise 3 in Clojure for the Brave and True requires:

Implement the assoc-in function. Hint: use the assoc function and define its parameters as [m [k & ks] v].

Although I have found this solution (see lines 39-54), I wondered if there was a different way of doing it. When working on the previous exercise, I found this very clear answer by jbm on implementing the comp function to be very helpful.

I've been trying to reduce a partial assoc over a conjoined list of keys and apply the returned function to the final value:

(defn my-part-assoc [m k]
  (partial assoc m k))

((reduce my-part-assoc {} [:one :two :three]) "val")

Needless to say, this doesn't work. I am new to Clojure and functional programming and fear my very basic understanding of reduce is leading me down the wrong path. Please can someone provide a more concise answer?

3 Answers 3

4

Shortly after posting, I found this, which gets the following definition from the Clojure GitHub repo:

(defn assoc-in
  ;; metadata elided
  [m [k & ks] v]
  (if ks
    (assoc m k (assoc-in (get m k) ks v))
    (assoc m k v)))
Sign up to request clarification or add additional context in comments.

2 Comments

I'm not sure if this constitutes a duplicate. Although I found my answer on Stack Overflow, I've left my question active as it's quite specific and may help others in same position.
notice, that unlike the core version, yours would fail with this: (assoc-in {} [:a :b :c] 1)...
1

I think Ooberdan's idea works in case of:

(defn my-as-in 
  "assoc val in nested map with nested key seq"                                
  [mp [ky & kysq] val]                                                          
  (if kysq                                                                     
    (assoc mp ky (my-as-in (get mp ky) kysq val))                                  
    (assoc mp ky val)))   

(my-as-in {} [:is :this :hello] 1)

gives {:is {:this {:hello 1}}} same as assoc-in...

Seems neat and idiomatic Clojure and it showed me the way after I got lost in reduce or multi arity type solutions.

Comments

0

Here is a solution that doesn't use "assoc-in" which seems to be a requirement:

(defn my-assoc-in
  [m [k & ks] v]
  (if (= (count ks) 0)
    (assoc m k v)
    (let [ordered-ks (reverse ks)
          first-m (get-in m (butlast (cons k ks)))]
      (assoc m k (reduce
                  (fn [curr-m next-k] (assoc {} next-k curr-m))
                  (assoc first-m (first ordered-ks) v)
                  (rest ordered-ks))))))```

1 Comment

This is needlessly complicated and definitely not something the author of the book expects a beginner to achieve :(

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.