# Create a Vector with values of variables defined by list of Symbols

**URL:** <https://discourse.julialang.org/t/create-a-vector-with-values-of-variables-defined-by-list-of-symbols/102307>\
**Category:** New to Julia\
**Tags:** question, metaprogramming\
**Created:** [July 31, 2023, 2:31pm UTC](https://discourse.julialang.org/t/create-a-vector-with-values-of-variables-defined-by-list-of-symbols/102307 "2023-07-31T14:31:27Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Neodym](https://avatars.discourse-cdn.com/v4/letter/n/ba8739/32.png) [@Neodym](https://discourse.julialang.org/u/Neodym)\
**Post date:** [July 31, 2023, 2:31pm UTC](https://discourse.julialang.org/t/create-a-vector-with-values-of-variables-defined-by-list-of-symbols/102307/1 "2023-07-31T14:31:27Z")

</div>

Hey fellow Julians,

I have a vector with symbols:

```julia
sym_list = [:(p.a), :(p.b), :(p.c)]

```

Given this `sym_list`, I’d like to automatically generate a function that plugs the values denoted by the symbols ( where `p` could be a `NamedTuple` or `struct`, for example) into a vector:

```julia
function flatten(p)
    return [p.a, p.b, p.c]
end

```

I’m stuck at synthesizing the inner part of the vector brackets:

```julia
function gen_flatten(sym_list)
    flatten_sym = gensym("flatten")
    func = quote
        function $flatten_sym(p)
            return [
                # What to put here?
            ]
        end
    end
    return eval(func)
end

```

I’ve tried splatting `sym_list` (i.e., put `$(sym_list...)` instead of the comment above) since that also works for calling functions. However, it didn’t work in this case and produced a syntax error:

```julia
syntax: invalid syntax "p.(Core._expr(:vect, sym_list...))"

```

How can I fix `gen_flatten()` such that it generates `flatten()`?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [July 31, 2023, 2:58pm UTC](https://discourse.julialang.org/t/create-a-vector-with-values-of-variables-defined-by-list-of-symbols/102307/2 "2023-07-31T14:58:58Z")

</div>

You could do this:

```julia
julia> p = (a=1, b=2, c=3)
(a = 1, b = 2, c = 3)

julia> sym_list = [:a, :b, :c];

julia> function return_vec(p,sym_list)
           map(s -> getfield(p, s), sym_list)
       end
return_vec (generic function with 1 method)

julia> return_vec(p, sym_list)
3-element Vector{Int64}:
 1
 2
 3

```

But are you sure you need to do that? What are you trying to do exactly?

---

<div class="post-metadata">

**Author:** ![Neodym](https://avatars.discourse-cdn.com/v4/letter/n/ba8739/32.png) [@Neodym](https://discourse.julialang.org/u/Neodym)\
**Post date:** [July 31, 2023, 3:04pm UTC](https://discourse.julialang.org/t/create-a-vector-with-values-of-variables-defined-by-list-of-symbols/102307/3 "2023-07-31T15:04:24Z")

</div>

Thanks for the suggestion. Unfortunately, it doesn’t fit my needs since no function is generated.

I am parsing a domain specific language and need to generate some code in order to use a Julia library / framework. Instead of creating some `.jl` file, I thought: Why not directly generate and `eval()` the `Expr`essions?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [July 31, 2023, 3:05pm UTC](https://discourse.julialang.org/t/create-a-vector-with-values-of-variables-defined-by-list-of-symbols/102307/4 "2023-07-31T15:05:51Z")

</div>

> [@Neodym](#):
>
> Thanks for the suggestion. Unfortunately, it doesn’t fit my needs since no function is generated.

You can return a function:

```julia
julia> function return_vec(p)
           return sym_list -> map(s -> getfield(p, s), sym_list)
       end
return_vec (generic function with 2 methods)

julia> return_vec(p)(sym_list)
3-element Vector{Int64}:
 1
 2
 3

```

---

<div class="post-metadata">

**Author:** ![Neodym](https://avatars.discourse-cdn.com/v4/letter/n/ba8739/32.png) [@Neodym](https://discourse.julialang.org/u/Neodym)\
**Post date:** [July 31, 2023, 3:09pm UTC](https://discourse.julialang.org/t/create-a-vector-with-values-of-variables-defined-by-list-of-symbols/102307/5 "2023-07-31T15:09:56Z")

</div>

That would be a working solution, I guess.

Still, I’d prefer to generate a “hardcoded” function (as in the `flatten()` example). However, I’ll use your approach in the meantime.

---

<div class="post-metadata">

**Author:** ![Neodym](https://avatars.discourse-cdn.com/v4/letter/n/ba8739/32.png) [@Neodym](https://discourse.julialang.org/u/Neodym)\
**Post date:** [July 31, 2023, 4:13pm UTC](https://discourse.julialang.org/t/create-a-vector-with-values-of-variables-defined-by-list-of-symbols/102307/6 "2023-07-31T16:13:56Z")

</div>

I figured it out by reverse-engineering the AST of `flatten()`:

```julia
function gen_flatten(sym_list)
    flatten_sym = gensym("flatten")
    func = Expr(:function,
                Expr(:call, flatten_sym, :p),
                Expr(:block,
                    Expr(:return, Expr(:vect, sym_list...))
                )
            )
    return eval(func)
end

```

Example:

```julia
sym_list = [:(p.a), :(p.b), :(p.c)]
flatten = gen_flatten(sym_list)
flatten((a = 1, b = 2, c = 3))

```

For readability, I’d still be interested to see how to formulate it in the style of the original post instead of directly writing down the AST.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [July 31, 2023, 4:42pm UTC](https://discourse.julialang.org/t/create-a-vector-with-values-of-variables-defined-by-list-of-symbols/102307/7 "2023-07-31T16:42:28Z")

</div>

Another option that produces a similar result, without meta-programming, is to use a callable struct:

```julia
julia> struct Flatten{L}
           sym_list::L
       end

julia> (f::Flatten)(p) = map(s -> getfield(p, s), f.sym_list)

julia> flatten = Flatten([:a, :b, :c])
Flatten{Vector{Symbol}}([:a, :b, :c])

julia> p = (a=1, b=2, c=3)
(a = 1, b = 2, c = 3)

julia> flatten(p)
3-element Vector{Int64}:
 1
 2
 3

```
