Search code examples
clojurenested-lists

Clojure - using map recursively


If I have a list, I can use map to apply a function to each item of the list.

(map sqrt (list 1 4 9))

(1 2 3)

I can also use map in front of a list of lists:

(map count (list (list 1 2 3) (list 4 5)))

(4 5)

Now is there a way to apply sqrt to each number in the list of lists? I want to start from

(list (list 1 4 9) (list 16 25))

and obtain

((1 2 3)(4 5))

However, the following does not seem to work,

(map (map sqrt) (list (list 1 4 9) (list 16 25)))

nor the following.

(map (fn [x] (map sqrt x)) (list (list 1 4 9) (list 16 25)))

Why? (And how do I solve this?)


Solution

  • Your second to last version "nearly" works. Clojure has no automatic currying, so (map sqrt) is not partial application, but (map sqrt) returns a transducer, which takes one argument and returns a function with three different arities - so running your code there will give you back a function for each list of numbers.

    To make that work, you can use partial:

    user=> (map (partial map sqrt) (list (list 1 4 9) (list 16 25)))
    ((1 2 3) (4 5))
    

    And of course there is the obligatory specter answer:

    user=> (transform [ALL ALL] sqrt '((1 4 9)(16 25)))
    ((1 2 3) (4 5))