Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Clojure, second argument in map-indexed

Tags:

clojure

SPOILER ALERT: This is about answers to 4Clojure question 157, indexing sequences.

The fast version of this question: in (map-indexed #(vector %2 %1) [:a :b :c]), what is %2?

Indexing Sequences #157

Transform a sequence into a sequence of pairs containing the original elements along with their index.

(= (__ [:a :b :c]) [[:a 0] [:b 1] [:c 2]])
(= (__ [0 1 3]) '((0 0) (1 1) (3 2)))
(= (__ [[:foo] {:bar :baz}]) [[[:foo] 0] [{:bar :baz} 1]])

I pretty quickly managed an answer: #(map reverse (map-indexed vector %)), but saw seemingly better answers such as:

map-indexed #(vector %2 %1)

by user tomdmitriev.

The question: where does the second argument come from?

So, for (map-indexed #(vector %2 %1) [:a :b :c]), what is %2?

The docs for map-indexed state:

Returns a lazy sequence consisting of the result of applying f to 0 and the first item of coll, followed by applying f to 1 and the second item in coll, etc, until coll is exhausted. Thus function f should accept 2 arguments, index and item. Returns a stateful transducer when no collection is provided. -- my emphasis

Well, I also only provided one argument, the collection from the 4Clojure question. I'm not sure how this is working... is there some kind of an implied or implicit argument?

Thanks for any help clearing this up!

like image 798
Mallory-Erik Avatar asked Jul 01 '26 00:07

Mallory-Erik


1 Answers

The function passed to map-indexed is a function of [index item]. Easy to understand with:

 (map-indexed (fn [idx itm] [idx itm]) "item")
 ; ([0 "item"])

It is actually a apply_map_with_index

So back to your example, with:

 (map-indexed #(vector %2 %1) [:a :b :c])
 ; ([:a 0] [:b 1] [:c 2])

Will create a small sequence of vector, made from %2 the item, %1 the index.

You can also compare the above with the easy to understand:

 (map-indexed #(vector %1 %2) [:a :b :c])
 ; ([0 :a] [1 :b] [2 :c])

which creates a sequence of small vector of [index item].

EDIT:

If we decompose this in two steps, it gives:

  ; we need to define a function 
  ; with two parameters 
  (defn my-function [index item]
      (vector item index))

  ; map-indexed uses a function with 
  ; two parameters
  (map-indexed 
       my-function 
       [:a :b :c])
like image 120
Nicolas Modrzyk Avatar answered Jul 04 '26 00:07

Nicolas Modrzyk



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!