"apply map vector" idiom - How happens to be 2 functions?

Only map is being 'applied'. However the first argument to map is always itself a function. In this case vector is being prepended to the the sequence of arguments produced by (vec jpgList). vector here is not a second function being applied, it is the first argument in the sequence to which map is applied together with the rest.

You will see this idiom often when applying any higher order function that itself takes a function as an argument.


Read the documentation of apply:

user=> (doc apply)
-------------------------
clojure.core/apply
([f args] [f x args] [f x y args] [f x y z args] [f a b c d & args])
  Applies fn f to the argument list formed by prepending intervening arguments to args.
nil

So, (apply map vector (vec jpgList)) corresponds to f x args, so map will be applied to the the function vector, followed by the elements of (vec jpgList). Unlike Haskell, Clojure's map supports multiple collections to operate on. (vec jpgList) presumably is a nested vector, or list, like in the following example:

user=> (apply map vector [[1 2 3] [4 5 6]])
([1 4] [2 5] [3 6])  

What happened is, every element produced by map is the vector of each nth element of the elements of the nested vector. This function is also known as transpose in matrix operations.


apply accepts a function and its arguments. If called with more than two arguments, the middle arguments will be added as scalar arguments (like using partial). See the documentation for apply

In other words, all four of these are the same:

(apply (partial map vector) [[1 2 3 4] "abcd"])
(apply map [vector [1 2 3 4] "abcd"])
(apply map vector [[1 2 3 4] "abcd"])
(map vector [1 2 3 4] "a b c d")

All will return ([1 \a] [2 \b] [3 \c] [4 \d]).

Tags:

Clojure