# Is it possible to get the fieldnames of a struct inside a macro?

**URL:** <https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314>\
**Category:** General Usage\
**Created:** [January 13, 2020, 8:44pm UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314 "2020-01-13T20:44:53Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![rvignolo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rvignolo/32/33498_2.png) [@rvignolo](https://discourse.julialang.org/u/rvignolo)\
**Post date:** [January 13, 2020, 8:44pm UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/1 "2020-01-13T20:44:53Z")

</div>

Hi all,

I was wondering if it is possible to expand or get fieldnames of a DataType inside a macro. My instinct says it is not possible, but maybe someone knows a trick or something…

```nohighlight
struct DummyStruct
  a
  b
end

# return somehow the fieldnames in DummyStruct
@dummymacro(DummyStruct)

```

Please, notice that I want to build a function expression inside the macro using those fieldnames and that is why I need to get those fieldnames in the macro scope.

Thanks!

---

<div class="post-metadata">

**Author:** ![sswatson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sswatson/32/5135_2.png) [@sswatson](https://discourse.julialang.org/u/sswatson)\
**Post date:** [January 13, 2020, 8:48pm UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/2 "2020-01-13T20:48:50Z")

</div>

What about `fieldnames`?

---

<div class="post-metadata">

**Author:** ![rvignolo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rvignolo/32/33498_2.png) [@rvignolo](https://discourse.julialang.org/u/rvignolo)\
**Post date:** [January 13, 2020, 8:50pm UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/3 "2020-01-13T20:50:48Z")

</div>

Hi. Thank you for your reply.

However, please be aware that I want to get the fieldnames inside the macro.

I want to build a function expression inside the macro using those fieldnames.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [January 13, 2020, 8:55pm UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/4 "2020-01-13T20:55:42Z")

</div>

Can you instead have the macro generate code that calls fieldnames?

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [January 13, 2020, 8:55pm UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/5 "2020-01-13T20:55:59Z")

</div>

No. The macro only sees the symbol `:dummyvariable` but not what it points to (this is undefined at macro evaluation time). But the macro can create code which uses `fieldnames` to look up field-names.

---

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [January 13, 2020, 9:05pm UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/6 "2020-01-13T21:05:33Z")

</div>

```julia
julia> macro doit(T)
           fnames = fieldnames(eval(T))
           # better:
           # fieldnames(Core.eval( __module__ , T))
           @show fnames
       end
@doit (macro with 1 method)

julia> struct S;a;b;end

julia> @doit S
fnames = (:a, :b)
(:a, :b)

```

See also [Using eval inside macro? - #2 by yuyichao](https://discourse.julialang.org/t/using-eval-inside-macro/8183/2)

---

<div class="post-metadata">

**Author:** ![rvignolo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rvignolo/32/33498_2.png) [@rvignolo](https://discourse.julialang.org/u/rvignolo)\
**Post date:** [January 13, 2020, 9:30pm UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/7 "2020-01-13T21:30:25Z")

</div>

Hi @Oscar_Smith and @mauro3. Thanks for your reply. I get your suggestion, but I need those fieldnames to build the expression of a function, I cannot use `fieldnames` inside the function to solve my problem.

For example, I want to create a function that uses handlers for variables defined in a struct in order to be able to evaluate an expression:

```nohighlight
p -> begin

  # expand fieldnames in p
  a = p.a
  b = p.b

  # This expression is given by the user and I don't want to operate on it
  # because it might involve many things, i.e. I don't want to change it to 
  # p.a + p.b
  return a + b
end

```

Using `fieldnames` in this function does not solve the problem.

Any insight is welcome. Thanks!

---

<div class="post-metadata">

**Author:** ![rvignolo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rvignolo/32/33498_2.png) [@rvignolo](https://discourse.julialang.org/u/rvignolo)\
**Post date:** [January 13, 2020, 9:33pm UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/8 "2020-01-13T21:33:43Z")

</div>

Hi @jw3126, thanks for your reply. This is really really helpful!

I can even use @mauro3 package Parameters.jl to define a struct:

```nohighlight
julia> @doit(@with_kw struct foo 
         a = 1
         b = 2
       end)
(:a, :b)

```

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [January 13, 2020, 9:42pm UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/9 "2020-01-13T21:42:09Z")

</div>

That looks like a situation, where you might want to use a generated function instead of a macro. At least to me, that seems more idiomatic than calling `eval` inside a macro.

---

<div class="post-metadata">

**Author:** ![rvignolo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rvignolo/32/33498_2.png) [@rvignolo](https://discourse.julialang.org/u/rvignolo)\
**Post date:** [January 13, 2020, 9:51pm UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/10 "2020-01-13T21:51:06Z")

</div>

An example is welcome!

I will think about it as well.

---

<div class="post-metadata">

**Author:** ![sairus7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sairus7/32/10816_2.png) [@sairus7](https://discourse.julialang.org/u/sairus7)\
**Post date:** [January 13, 2020, 10:20pm UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/11 "2020-01-13T22:20:01Z")

</div>

See `@generated function staticschema`:  
[https://github.com/JuliaArrays/StructArrays.jl/blob/master/src/interface.jl](https://github.com/JuliaArrays/StructArrays.jl/blob/master/src/interface.jl)

Or `@generated foreachfield`:

[https://github.com/JuliaArrays/StructArrays.jl/blob/master/src/utils.jl](https://github.com/JuliaArrays/StructArrays.jl/blob/master/src/utils.jl)

Actually you can use `foreachfield` on a type declared in method signature (`where {T}` syntax)

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [January 13, 2020, 10:38pm UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/12 "2020-01-13T22:38:20Z")

</div>

> [@rvignolo](#):
>
> I was wondering if it is possible to expand or get fieldnames of a DataType inside a macro

No, for exactly the same reasons as in [Unpack named tuples (does anyone know how to do it?) - #9 by rdeits](https://discourse.julialang.org/t/unpack-named-tuples-does-anyone-know-how-to-do-it/32456/9)

The macro is, in general, expanded before the struct exists and certainly before the symbol being passed into the macro has a value. This just isn’t something macros can do for you, at least not in a way you can rely on.

An `@generated` function is probably the solution here, although it’s hard to know without knowing what you’re actually trying to accomplish. Can you give any more context?

---

<div class="post-metadata">

**Author:** ![sairus7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sairus7/32/10816_2.png) [@sairus7](https://discourse.julialang.org/u/sairus7)\
**Post date:** [January 13, 2020, 11:00pm UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/13 "2020-01-13T23:00:39Z")

</div>

I thought that parametric methods are specialized in a way that you have “unrolled” `fieldnames` code on types that are in method parmeters. Just because nothing prevents from optimizing it at compile time.

---

<div class="post-metadata">

**Author:** ![rvignolo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rvignolo/32/33498_2.png) [@rvignolo](https://discourse.julialang.org/u/rvignolo)\
**Post date:** [January 13, 2020, 11:04pm UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/14 "2020-01-13T23:04:43Z")

</div>

> [@rdeits](#):
>
> No, for exactly the same reasons as in [Unpack named tuples (does anyone know how to do it?)](https://discourse.julialang.org/t/unpack-named-tuples-does-anyone-know-how-to-do-it/32456/9)

What about @jw3126 [response](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/6)? It seems correct to me. Can you check it out?

> [@rdeits](#):
>
> Can you give any more context?

Yes, of course. I want to create a function expression inside a macro by receiving a DataType and a expression that needs to be evaluated using those attributes inside the struct.

So for example:

```Julia
# define the struct with defaulted values
@with_kw struct foo{T}
  a::T = 1
  b::T = 2
end

f = @bar begin
   params: foo
   expr: a + b
end

```

where the macro bar builds the function expression:

```Julia
foo -> begin

  # expand fieldnames in p
  a = foo.a
  b = foo.b

  # This expression is given by the user and I don't want to operate on it
  # because it might involve many things, i.e. I don't want to change it to 
  # foo.a + foo.b
  return a + b
end

```

I know that I can define the parameters inside the macro bar, which will allow me to know the parameters. However, I wanted to make them separatelye because they might be in separate windows in the front end (User Interface).

Thanks!

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [January 13, 2020, 11:12pm UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/15 "2020-01-13T23:12:34Z")

</div>

Sorry, I’m on a phone right now so I can’t run code, but try something like this:

```julia
function foo(T)
  @doit(T)
end

```

The macro just gets the symbol T. It has _no access_ to the value that T is bound to when you call `foo`. After all, you haven’t even called `foo` yet, so how could it?

The given example happens to work because it only involves global variables that were already defined at the time the macro was expanded. You can’t rely on that being the case.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [January 13, 2020, 11:26pm UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/16 "2020-01-13T23:26:36Z")

</div>

As for your actual task, am I correct in assuming that the expression `a + b` is coming in as run-time data, such as a parsed string from a user interface? If so, then you probably need to call `eval` on _something_ because there’s no other way to cause a function to come into existence at run-time.

A related question is: are the symbols inside the expression _always_ supposed to be fields of the struct? If so, can you just transform every symbol `a` into `foo.a`? In that case, you don’t need to know the field types of anything. I suspect that’s probably too simple for your real application, but it’s worth considering.

---

<div class="post-metadata">

**Author:** ![rvignolo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rvignolo/32/33498_2.png) [@rvignolo](https://discourse.julialang.org/u/rvignolo)\
**Post date:** [January 14, 2020, 1:16am UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/17 "2020-01-14T01:16:12Z")

</div>

> [@rdeits](#):
>
> The given example happens to work because it only involves global variables that were already defined at the time the macro was expanded. You can’t rely on that being the case.

But it involves a DataType, not a global variable, right?

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [January 14, 2020, 2:09am UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/18 "2020-01-14T02:09:09Z")

</div>

> [@rvignolo](#):
>
> But it involves a DataType, not a global variable, right?

I’m not sure I understand the distinction you’re making. In any case, it’s easy to find examples that break it:

```julia
julia> macro doit(T)
           fnames = fieldnames(eval(T))
           # better:
           # fieldnames(Core.eval( __module__ , T))
           @show fnames
       end
@doit (macro with 1 method)

julia> function foo(T)
         @doit(T)
       end
ERROR: LoadError: UndefVarError: T not defined

```

Note the error occurs before we even try to call `foo`.

---

<div class="post-metadata">

**Author:** ![rvignolo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rvignolo/32/33498_2.png) [@rvignolo](https://discourse.julialang.org/u/rvignolo)\
**Post date:** [January 14, 2020, 3:00am UTC](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/19 "2020-01-14T03:00:53Z")

</div>

Yeah, I get that. It is not possible to define that function at all. But the example should be something like:

```julia
julia> macro doit(T)
         fnames = fieldnames(eval(T))
         # better:
         # fieldnames(Core.eval( __module__ , T))
         @show fnames
       end
@doit (macro with 1 method)

julia> struct bar
         a
         b
       end

julia> function foo(x::bar)
         @doit(bar)
       end
fnames = (:a, :b)
foo (generic function with 1 method)

julia> foo(bar(1,2))
(:a, :b)

```

Anyway, I get your concern (the code above is not the best). Let me first figure out which path I decide to follow to build my macro. Once I get that, I will post it. I have collected many useful ideas to process.
