# How to evaluate symbol as a "variable" inside a macro?

**URL:** <https://discourse.julialang.org/t/how-to-evaluate-symbol-as-a-variable-inside-a-macro/103607>\
**Category:** General Usage\
**Tags:** question, package, macros, metaprogramming\
**Created:** [September 7, 2023, 10:11am UTC](https://discourse.julialang.org/t/how-to-evaluate-symbol-as-a-variable-inside-a-macro/103607 "2023-09-07T10:11:43Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Qfl3x](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/qfl3x/32/224645_2.png) [@Qfl3x](https://discourse.julialang.org/u/Qfl3x)\
**Post date:** [September 7, 2023, 10:11am UTC](https://discourse.julialang.org/t/how-to-evaluate-symbol-as-a-variable-inside-a-macro/103607/1 "2023-09-07T10:11:43Z")

</div>

Hello, I’m currently trying to implement `merge` on `ComponentArray`s. I’ve taken inspiration from `NamedTuple`s in the stdlib [here](https://github.com/JuliaLang/julia/blob/1305f40195b1b729ce465114b8c567f6b3688833/base/namedtuple.jl#L326C1-L335C4), and wrote a macro and a function: (instead of the `Expr`)

```julia
using ComponentArrays
c1 = ComponentArray(a=2, b=5)
c2 = ComponentArray(b=1, g=2)

macro append_component_array(parent_array, keyname, val)
    return esc(:($parent_array = ComponentArray($parent_array, $keyname = $val) ))
end

function merge_test(cvec1::ComponentVector{T1}, cvec2::ComponentVector{T2}) where {T1, T2}
    typed_dict = ComponentVector{promote_type(T1, T2)}(cvec1)
    for key in valkeys(cvec2)
        keyname = ComponentArrays.getval(key)
        val = cvec2[key]
        @append_component_array(typed_dict, keyname, val)
    end
    typed_dict
end

```

However, I can’t seem to get `keyname` to evaluate properly in the macro to a “variable”:

```julia
>julia merge_test(c1,c2)
ComponentVector{Int64}(a = 2, b = 5, keyname = 2)

```

I can do this with `eval` easily, though it will kill precompilation.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [September 7, 2023, 11:26am UTC](https://discourse.julialang.org/t/how-to-evaluate-symbol-as-a-variable-inside-a-macro/103607/2 "2023-09-07T11:26:05Z")

</div>

Macros don’t evaluate symbols, it expands during the definition, before the method is ran and before the variables have values. Your macro just interpolates `:typed_dict`, `:keyname`, and `:val` into a line `typed_dict = ComponentArray(typed_dict, keyname = val)`. Forgetting the macro for a second, you need a different line where a keyword is a runtime Symbol value rather than a fixed variable name. Try `typed_dict = ComponentArray(typed_dict; keyname => val)`

---

<div class="post-metadata">

**Author:** ![Qfl3x](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/qfl3x/32/224645_2.png) [@Qfl3x](https://discourse.julialang.org/u/Qfl3x)\
**Post date:** [September 7, 2023, 11:29am UTC](https://discourse.julialang.org/t/how-to-evaluate-symbol-as-a-variable-inside-a-macro/103607/3 "2023-09-07T11:29:54Z")

</div>

Huh, that works.

Though why does `dump` not work?

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [September 7, 2023, 11:30am UTC](https://discourse.julialang.org/t/how-to-evaluate-symbol-as-a-variable-inside-a-macro/103607/4 "2023-09-07T11:30:44Z")

</div>

I don’t know what you mean, you didn’t use `dump` anywhere before.

---

<div class="post-metadata">

**Author:** ![Qfl3x](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/qfl3x/32/224645_2.png) [@Qfl3x](https://discourse.julialang.org/u/Qfl3x)\
**Post date:** [September 7, 2023, 11:32am UTC](https://discourse.julialang.org/t/how-to-evaluate-symbol-as-a-variable-inside-a-macro/103607/5 "2023-09-07T11:32:30Z")

</div>

I tried to use `dump` to use `keyname` as a variable, thinking it would work based on how I understood it. Though, the result is either a crash (if I try to interpolate the dump), or nothing (if I don’t).

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [September 7, 2023, 11:33am UTC](https://discourse.julialang.org/t/how-to-evaluate-symbol-as-a-variable-inside-a-macro/103607/6 "2023-09-07T11:33:14Z")

</div>

Provide the `dump` call code, I can’t imagine what you mean.

---

<div class="post-metadata">

**Author:** ![Qfl3x](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/qfl3x/32/224645_2.png) [@Qfl3x](https://discourse.julialang.org/u/Qfl3x)\
**Post date:** [September 7, 2023, 11:39am UTC](https://discourse.julialang.org/t/how-to-evaluate-symbol-as-a-variable-inside-a-macro/103607/7 "2023-09-07T11:39:22Z")

</div>

```julia
macro append_component_array(parent_array, keyname, val)
    return esc(:($parent_array = ComponentArray($parent_array, $dump(:(:keyname)) = $val) ))
end

```

or

```julia
macro append_component_array(parent_array, keyname, val)
    dump(:(:keyname))
    return esc(:($parent_array = ComponentArray($parent_array, $keyname = $val) ))
end

```

or

```julia
macro append_component_array(parent_array, keyname, val)
    key = dump(:(:keyname))
    return esc(:($parent_array = ComponentArray($parent_array, $key = $val) ))
end

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [September 7, 2023, 11:48am UTC](https://discourse.julialang.org/t/how-to-evaluate-symbol-as-a-variable-inside-a-macro/103607/8 "2023-09-07T11:48:01Z")

</div>

`dump` prints a value in a tree-like way to a maximum depth defaulting at 8, then returns `nothing`. You’re interpolating the value `nothing` where a `Symbol` instance is expected for a keyword.

---

<div class="post-metadata">

**Author:** ![skleinbo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skleinbo/32/36080_2.png) [@skleinbo](https://discourse.julialang.org/u/skleinbo)\
**Post date:** [September 7, 2023, 12:22pm UTC](https://discourse.julialang.org/t/how-to-evaluate-symbol-as-a-variable-inside-a-macro/103607/9 "2023-09-07T12:22:31Z")

</div>

As the question stands, I doubt meta programming is the answer. In particular, I don’t see the value of the macro over a function.

Maybe you could explain what the end goal is and why you believe meta programming is the correct way to get there. I’m saying this, because more often than not, it isn’t.

---

<div class="post-metadata">

**Author:** ![Qfl3x](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/qfl3x/32/224645_2.png) [@Qfl3x](https://discourse.julialang.org/u/Qfl3x)\
**Post date:** [September 7, 2023, 1:00pm UTC](https://discourse.julialang.org/t/how-to-evaluate-symbol-as-a-variable-inside-a-macro/103607/10 "2023-09-07T13:00:19Z")

</div>

I didn’t see a way to implement it via a function, but apparently there is.

---

<div class="post-metadata">

**Author:** ![skleinbo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skleinbo/32/36080_2.png) [@skleinbo](https://discourse.julialang.org/u/skleinbo)\
**Post date:** [September 7, 2023, 1:11pm UTC](https://discourse.julialang.org/t/how-to-evaluate-symbol-as-a-variable-inside-a-macro/103607/11 "2023-09-07T13:11:38Z")

</div>

I am still not really sure what “it” is. If you simply want to merge two ComponentArrays, the package has you covered already:

```julia
c1 = ComponentArray(a=2, b=5, c=[10, 20])
c2 = ComponentArray(b=1, g=2)

julia> ComponentArray(c1; c2...)
ComponentVector{Int64}(a = 2, b = 1, c = [10, 20], g = 2)

```

---

<div class="post-metadata">

**Author:** ![Qfl3x](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/qfl3x/32/224645_2.png) [@Qfl3x](https://discourse.julialang.org/u/Qfl3x)\
**Post date:** [September 7, 2023, 1:17pm UTC](https://discourse.julialang.org/t/how-to-evaluate-symbol-as-a-variable-inside-a-macro/103607/12 "2023-09-07T13:17:59Z")

</div>

I’ve tried using it, though it doesn’t support Reverse AD. I thought if I try to implement it like Base.merge for NamedTuple, maybe it’ll work.

---

<div class="post-metadata">

**Author:** ![skleinbo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skleinbo/32/36080_2.png) [@skleinbo](https://discourse.julialang.org/u/skleinbo)\
**Post date:** [September 7, 2023, 1:23pm UTC](https://discourse.julialang.org/t/how-to-evaluate-symbol-as-a-variable-inside-a-macro/103607/13 "2023-09-07T13:23:25Z")

</div>

I see. The better course of action is to open an issue with `ComponentArrays.jl`, or write a `ChainRulesCore.rrule` yourself. Ideally ultimately making a PR.

The issue however has already been raised [Missing ChainRule for `ComponentVector(a; b...)` · Issue #207 · jonniedie/ComponentArrays.jl · GitHub](https://github.com/jonniedie/ComponentArrays.jl/issues/207) and it looks like a solution might be near 🙂

I would imagine writing a proper pullback will turn out to be a lot more fruitful than implementing merge again.
