0

In clojure, I would like to apply a function to all the elements of a sequence and return a map with the results where the keys are the elements of the sequence and the values are the elements of the mapped sequence.

I have written the following function function. But I am wondering why such a function is not part of clojure. Maybe it's not idiomatic?

(defn map-to-object[f lst]
   (zipmap lst (map f lst)))


(map-to-object #(+ 2 %) [1 2 3]) => {1 3, 2 4, 3 5}
5
  • 1
    Nothing wrong with that. You might also see (into {} (map (juxt identity f) coll)). A similar function in core is memoize for the common use-case. Commented Mar 6, 2014 at 13:00
  • @A.Webb Could you elaborate on the connection to memoize? Commented Mar 6, 2014 at 13:46
  • If the function is f, and the resultant map is m then (f x) and (m x) have the same value in the lst domain. However, the values of (m x) have been precalculated, in other words, memoized. Commented Mar 6, 2014 at 14:24
  • @A.Webb I'm looking at the code of memoize but I see nothing related to my question Commented Mar 6, 2014 at 21:21
  • 1
    I can't fit a full explanation in a comment, so see new answer below. Commented Mar 7, 2014 at 1:33

2 Answers 2

2

Your function is perfectly idiomatic.

For a fn to be part of core, I think it has to be useful to most people. What is part of the core language and what is not is quite debatable. Just think about the amount of StringUtils classes that you can find in Java.

Sign up to request clarification or add additional context in comments.

Comments

2

My comments were going to get too long winded, so...

  1. Nothing wrong with your code whatsoever.
  2. You might also see (into {} (map (juxt identity f) coll))
  3. One common reason for doing this is to cache the results of a function over some inputs.
  4. There are other use-cases for what you have done, e.g. when a hash-map is specifically needed.
  5. If and only if #3 happens to be your use case, then memoize does this for you.

If the function is f, and the resultant map is m then (f x) and (m x) have the same value in the domain. However, the values of (m x) have been precalculated, in other words, memoized.

Indeed memoize does exactly the same thing behind the scene, it just doesn't give direct access to the map. Here's a tiny modification to the source of memoize to see this.

(defn my-memoize
  "Exactly the same as memoize but the cache memory atom must
  be supplied as an argument."
  [f mem]
  (fn [& args]
    (if-let [e (find @mem args)]
      (val e)
      (let [ret (apply f args)]
        (swap! mem assoc args ret)
        ret))))

Now, to demonstrate

(defn my-map-to-coll [f coll] 
  (let [m (atom {})
        g (my-memoize f m)]
    (doseq [x coll] (g x))
    @m))

And, as in your example

(my-map-to-coll #(+ 2 %) [1 2 3])
;=> {(3) 5, (2) 4, (1) 3}

But note that the argument(s) are enclosed in a sequence as memoize handles multiple arity functions as well.

Comments

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.