Reputation: 796
Here is a sample from my mini code where I copied from clojure docs site.
(apply map vector (vec jpgList))
I guess map and vector are both functions, but apply takes only one function. How come in here apply takes two functions?
Upvotes: 9
Views: 3631
Reputation: 87
Consider this:
user=> (let [n1 1
#_=> n2 2
#_=> n-coll [n1 n2]]
#_=> (=
#_=> (apply + 999 n-coll)
#_=> (+ 999 n1 n2)))
true
'apply' applies + to the argument list formed by prepending 999 to n-coll. If you substitute map for + and vector for 999 when the collection in question is made of vectors:
user=> (let [r1 [1 2 3]
#_=> r2 [4 5 6]
#_=> r-coll [r1 r2]]
#_=> (=
#_=> (apply map vector r-coll)
#_=> (map vector r1 r2)))
true
Upvotes: 0
Reputation: 31621
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])
.
Upvotes: 5
Reputation: 8344
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.
Upvotes: 2
Reputation: 34800
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.
Upvotes: 12