Welcome! Please see the About page for a little more info on how this works.

0 votes
in Clojure by
edited by

Hi folks,

It seems like when I'm calling conj with 3 arguments, then arg2 gets added as a vector whereas arg3 is not.

It is doing what I expect with 2 args:
(apply conj [{:some :map}] [{:some-other :other-map}])
=> [{:some :map} {:some-other :other-map}]

It is adding the second arg as a vector, when I call conj with 3 args
(apply conj [{:some :map}] [{:some-other :other-map}] nil)
=> [{:some :map} [{:some-other :other-map}]]

(apply conj [{:some :map}] [{:some-other :other-map}] [{:something :else}])
=> [{:some :map} [{:some-other :other-map}] {:something :else}]

I'm curious to understand why conj shows this behaviour with 3 args.
Thanks

1 Answer

+1 vote
by

apply takes individual values and then as its last argument, a collection of remaining values, so that last argument is always different. I think that's the fundamental bit you're missing. The last arg collection's values are spliced into the invocation.

Generic example:

(f 1 2 3 4) can be written as any of these (these are all equivalent):

(apply f 1 2 3 4 nil)
(apply f 1 2 3 4 [])
(apply f 1 2 3 [4])
(apply f 1 2 [3 4])
(apply f 1 [2 3 4])
(apply f [1 2 3 4])

In your example, conj is a function that will take a collection first, so the first arg should always be a vector. And then you expect spliced values to come in with subsequent values. Using numbers instead for brevity these are equivalent:

(conj [1] 2)
(apply conj [1] 2 nil)
(apply conj [1] [2])

Or 3 values:

(conj [1] 2 3)
(apply conj [1] 2 3 nil)
(apply conj [1] 2 3 [])
(apply conj [1] 2 [3])
(apply conj [1] [2 3])

by
edited by
Thanks a lot, just clicked.
...