"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])
.