# Expanding a vector to it's individual elements with a macro

**URL:** https://clojureverse.org/t/expanding-a-vector-to-its-individual-elements-with-a-macro/6455
**Category:** Troubleshooting
**Tags:** clojure
**Created:** [August 28, 2020, 11:07am UTC](https://clojureverse.org/t/expanding-a-vector-to-its-individual-elements-with-a-macro/6455 "2020-08-28T11:07:10Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![ashwinbhaskar](https://clojureverse.org/user_avatar/clojureverse.org/ashwinbhaskar/32/2045_2.png) [@ashwinbhaskar](https://clojureverse.org/u/ashwinbhaskar)
#### Post date: [August 28, 2020, 11:07am UTC](https://clojureverse.org/t/expanding-a-vector-to-its-individual-elements-with-a-macro/6455/1 "2020-08-28T11:07:10Z")

</div>

I am trying to construct an SQL query with dynamic parameters in the `in` sections. I do not want to use honeysql here. I am trying to do this with a macro. Note: `apply` will not work here.

```auto
(defmacro expand-second-arg
  [q b]
  `[~q ~@b])

(defn find [ids]
  (let [query "SELECT * FROM foo WHERE id in (?,?)"]
        (jdbc/execute! datasource (expand-second-arg query ids))))

```

But I get this error

```auto
error while macroexpancing..
Don't know how to create ISeq from: clojure.lang.Symbol

```

But it works fine when I use the macro with values directly. For example this

```auto
(expand-second-arg "SELECT * FROM foo WHERE id in (?,?)" ["id_1" "id_2"])

```

works and returns `["SELECT * FROM foo WHERE id in (?,?)" "id_1" "id_2"]`.

---

<div class="post-metadata">

### Author: ![bsless](https://clojureverse.org/letter_avatar_proxy/v4/letter/b/6f9a4e/32.png) [@bsless](https://clojureverse.org/u/bsless)
#### Post date: [August 28, 2020, 12:15pm UTC](https://clojureverse.org/t/expanding-a-vector-to-its-individual-elements-with-a-macro/6455/2 "2020-08-28T12:15:15Z")

</div>

It’s not working because macros are evaluated at read-time, not run time. Since `ids` is not known at read time you can’t expand it with a macro. You want to use the function apply, as in `(apply vector q ids)`

---

<div class="post-metadata">

### Author: ![ashwinbhaskar](https://clojureverse.org/user_avatar/clojureverse.org/ashwinbhaskar/32/2045_2.png) [@ashwinbhaskar](https://clojureverse.org/u/ashwinbhaskar)
#### Post date: [August 28, 2020, 12:19pm UTC](https://clojureverse.org/t/expanding-a-vector-to-its-individual-elements-with-a-macro/6455/3 "2020-08-28T12:19:40Z")

</div>

my bad. Yes, vector works fine. Thank you:)

---

<div class="post-metadata">

### Author: ![seancorfield](https://clojureverse.org/user_avatar/clojureverse.org/seancorfield/32/195_2.png) [@seancorfield](https://clojureverse.org/u/seancorfield)
#### Post date: [August 28, 2020, 4:13pm UTC](https://clojureverse.org/t/expanding-a-vector-to-its-individual-elements-with-a-macro/6455/4 "2020-08-28T16:13:05Z")

</div>

I would probably use `(into [query] ids)` here. I think it’s clearer and I would expect it to be faster. I try to avoid `apply` unless it’s absolutely necessary.

---

<div class="post-metadata">

### Author: ![madbonkey](https://clojureverse.org/user_avatar/clojureverse.org/madbonkey/32/575_2.png) [@madbonkey](https://clojureverse.org/u/madbonkey)
#### Post date: [August 29, 2020, 9:54am UTC](https://clojureverse.org/t/expanding-a-vector-to-its-individual-elements-with-a-macro/6455/5 "2020-08-29T09:54:42Z")

</div>

I think clarity is subjective here, but why would you expect it to be faster? Is apply that bad or is into that optimized?

---

<div class="post-metadata">

### Author: ![seancorfield](https://clojureverse.org/user_avatar/clojureverse.org/seancorfield/32/195_2.png) [@seancorfield](https://clojureverse.org/u/seancorfield)
#### Post date: [August 29, 2020, 6:06pm UTC](https://clojureverse.org/t/expanding-a-vector-to-its-individual-elements-with-a-macro/6455/6 "2020-08-29T18:06:44Z")

</div>

Just looking at the source of the two functions `apply` and `into` makes me think `into` would be faster, so I ran a quick benchmark with Criterium and, with an `ids` list of 10 numbers, `into` is about twice as fast:

```auto
user=> (b/quick-bench (into [10] ids))
Evaluation count : 1872594 in 6 samples of 312099 calls.
             Execution time mean : 364.756664 ns
    Execution time std-deviation : 80.701919 ns
   Execution time lower quantile : 310.080901 ns ( 2.5%)
   Execution time upper quantile : 474.054445 ns (97.5%)
                   Overhead used : 7.683004 ns
nil
user=> (b/quick-bench (apply vector 10 ids))
Evaluation count : 971178 in 6 samples of 161863 calls.
             Execution time mean : 683.204222 ns
    Execution time std-deviation : 94.196118 ns
   Execution time lower quantile : 614.400740 ns ( 2.5%)
   Execution time upper quantile : 808.153578 ns (97.5%)
                   Overhead used : 7.683004 ns
nil
user=> 

```

(I ran those several times – the results were pretty consistent)

This is the relevant arity from `apply`:

```auto
  ([^clojure.lang.IFn f x args]
     (. f (applyTo (list* x args))))

```

and that arity of `list*`:

```auto
  ([a args] (cons a args))

```

So it’s going to build a (lazy) sequence of all the arguments and then call `.applyTo` (from `IFn`). The relevant Java code for that can be seen here: [https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/AFn.java#L227-L239](https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/AFn.java#L227-L239)

That walks all 11 elements of the arguments to call `.invoke`, and then then relevant arity of `vector` for 11 args is going to be:

```auto
  ([a b c d e f & args]
     (. clojure.lang.LazilyPersistentVector (create (cons a (cons b (cons c (cons d (cons e (cons f args))))))))))

```

which builds up another (lazy) sequence of all the arguments(!) and finally creates a vector from them.

By contrast, `into` does this:

```auto
  ([to from]
     (if (instance? clojure.lang.IEditableCollection to)
       (with-meta (persistent! (reduce conj! (transient to) from)) (meta to))
       (reduce conj to from)))

```

`[10]` is an `IEditableCollection` so we take the (fast) transient route to `reduce` with an `init` value, which is an optimized path that makes a single pass over the collection (although you pay the cost of constructing a persistent version of the transient vector at the end).

---

<div class="post-metadata">

### Author: ![system](https://clojureverse.org/uploads/default/original/2X/5/51079bf9e4b7d9466242c06cf1e43b9f8bd6da14.png) [@system](https://clojureverse.org/u/system)
#### Post date: [February 28, 2021, 6:06am UTC](https://clojureverse.org/t/expanding-a-vector-to-its-individual-elements-with-a-macro/6455/7 "2021-02-28T06:06:45Z")

</div>

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.
