3
votes

I'm trying to write a more general map function for Clojure, but am unable to map a function over a nested vector. In particular the the map should admit a parameter n, which allows level specification of the nesting.

Here's what I've written so far, which fails with nested vectors:

(defn cloj-maps 
([f x]     (vec (map f x)))
([f x y]   (vec (map f x y)))
([f x y z] (vec (map f x y z))))

Here is a sample of what I am trying to input/output:

Input 1: (inc [[1 2] [3 4]] 1) where inc is input function, [[...]] is nested vector, and 1 is level specification.

Output1: [[2 3] [4 5]]

Symbolically [f[a b] f[c d]] which is mapping at the top level.

Input 2: (inc [[1 2] [3 4]] 2)

Output 2: [[3 4] [5 6]]

Symbolically [f[f[a] f[b]] f[f[c] f[d]]] where I have used f for function, and replaced {1,2,3,4}->{a,b,c,d}. Here the input parameter 2 implies mapping at levels 1 and 2, hence f "wrapped" around each element and each vector.

1
I can't make sense of your example. What does [f[f[a] f[b]] f[f[c] f[d]]] mean? I thought the n ("level specification of nesting") parameter would say how deeply the vectors are nested, but that doesn't seem to be what's going on in the examples.DaoWen
The purpose of n is to specify at what levels you want to map. For a nested vector such as [[[1 2 3]]] one might choose n=3. If f stands for function, then you'd expect [f[f[f[1] f[2] f[3]]]].sunspots
Your notation still doesn't make sense. What is [f[f[f[1] f[2] f[3]]]] supposed to mean?DaoWen
Looking at the segment [f[1] f[2] f[3]] entails mapping the function over each element in the vector, i.e. (map inc [1 2 3]). Then f, or inc here, would be mapped over the vector [2 3 4] producing [3 4 5]. Since, n was 3 here the output would yield [4 5 6].sunspots

1 Answers

3
votes

I don't understand why you would want to do this, but this might do what you're looking for:

(defn cloj-maps [f n x]
  (let [f' (nth (iterate #(comp f %) identity) n)]
    ((fn deep [y]
        (if (vector? y)
          (mapv deep y)
          (f' y)))
       x)))

Sample outputs:

user=> (cloj-maps inc 0 [[1 2] [3 4]])
[[1 2] [3 4]]
user=> (cloj-maps inc 1 [[1 2] [3 4]])
[[2 3] [4 5]]
user=> (cloj-maps inc 2 [[1 2] [3 4]])
[[3 4] [5 6]]
user=> (cloj-maps inc 3 [[1 2] [3 4]])
[[4 5] [6 7]]
user=> (cloj-maps inc 4 [[1 2] [3 4]])
[[5 6] [7 8]]