# Extracting all struct fields

**URL:** <https://discourse.julialang.org/t/extracting-all-struct-fields/36115>\
**Category:** General Usage\
**Created:** [March 17, 2020, 9:24pm UTC](https://discourse.julialang.org/t/extracting-all-struct-fields/36115 "2020-03-17T21:24:27Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![francesco.alemanno](https://avatars.discourse-cdn.com/v4/letter/f/e8c25b/32.png) [@francesco.alemanno](https://discourse.julialang.org/u/francesco.alemanno)\
**Post date:** [March 17, 2020, 9:24pm UTC](https://discourse.julialang.org/t/extracting-all-struct-fields/36115/1 "2020-03-17T21:24:27Z")

</div>

ideally i would like to do this

```julia
struct MyStruct
   a
   b
   c
end

function calculation(C::MyStruct)
   fieldnames(MyStruct)... = C
   2a+3b+c
end

```

i was trying this workaround

```julia

struct My
    a
    b
    c
end

function __unpack_genexpr(S)
    a=quote
    end
    for x in fieldnames(typeof(S))
        a=quote
            $(a)
            $x=$S.$x
        end
    end
    a
end
macro unpack(S)
    :(eval($__unpack_genexpr($S)))
end

function bla()
    @unpack My(6,7,8)
    a,b,c
end

bla() # (6,7,8)

```

it is ugly as hell and it leaks in the main module, what can i do?

---

<div class="post-metadata">

**Author:** ![mforets](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mforets/32/298_2.png) [@mforets](https://discourse.julialang.org/u/mforets)\
**Post date:** [March 17, 2020, 9:26pm UTC](https://discourse.julialang.org/t/extracting-all-struct-fields/36115/2 "2020-03-17T21:26:03Z")

</div>

> **[GitHub - mauro3/UnPack.jl: \`@pack!\` and \`@unpack\` macros](https://github.com/mauro3/UnPack.jl)**
>
> \`@pack!\` and \`@unpack\` macros. Contribute to mauro3/UnPack.jl development by creating an account on GitHub.

---

<div class="post-metadata">

**Author:** ![francesco.alemanno](https://avatars.discourse-cdn.com/v4/letter/f/e8c25b/32.png) [@francesco.alemanno](https://discourse.julialang.org/u/francesco.alemanno)\
**Post date:** [March 17, 2020, 9:26pm UTC](https://discourse.julialang.org/t/extracting-all-struct-fields/36115/3 "2020-03-17T21:26:39Z")

</div>

it is not the same, i want to extract all fields automatically

---

<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:** [March 17, 2020, 9:58pm UTC](https://discourse.julialang.org/t/extracting-all-struct-fields/36115/4 "2020-03-17T21:58:46Z")

</div>

No, I’m afraid there’s no way to do this because there is no way to dynamically create local variables. See [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) and [Is it possible to get the fieldnames of a struct inside a macro? - #15 by rdeits](https://discourse.julialang.org/t/is-it-possible-to-get-the-fieldnames-of-a-struct-inside-a-macro/33314/15) for some related discussion.

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [March 18, 2020, 11:34am UTC](https://discourse.julialang.org/t/extracting-all-struct-fields/36115/5 "2020-03-18T11:34:45Z")

</div>

Maybe with a generated function?

```julia
struct MyStruct
   a
   b
   c
end

@generated function calculation(ms::MyStruct)
    assignments = Expr(:block, [
        :($field = ms.$field)
        for field in fieldnames(ms)
    ]...)
    quote
        $assignments
        2a+3b+c
    end
end

```

```julia
julia> calculation(MyStruct(1,2,3))
11

```

The above implementation has (at least) the caveat that the name used for the function argument (`ms` in this case) must not conflict with any of the field names.

But I know that writing generated functions is often frowned upon; please let me know if there is something I overlooked.

---

<div class="post-metadata">

**Author:** ![thautwarm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thautwarm/32/37760_2.png) [@thautwarm](https://discourse.julialang.org/u/thautwarm)\
**Post date:** [March 18, 2020, 12:46pm UTC](https://discourse.julialang.org/t/extracting-all-struct-fields/36115/6 "2020-03-18T12:46:45Z")

</div>

implementation of `@open` in [ParametrisedModule](https://github.com/thautwarm/ParameterisedModule.jl) can be what you want.

---

<div class="post-metadata">

**Author:** ![thautwarm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thautwarm/32/37760_2.png) [@thautwarm](https://discourse.julialang.org/u/thautwarm)\
**Post date:** [March 18, 2020, 12:51pm UTC](https://discourse.julialang.org/t/extracting-all-struct-fields/36115/7 "2020-03-18T12:51:04Z")

</div>

> [@francesco.alemanno](#):
>
> it is ugly as hell and it leaks in the main module, what can i do?

You can use macro manipulation libraries(like MacroTools) to make it look pretty easy and short, and use `esc` properly to avoid scoping issues.

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [March 18, 2020, 3:03pm UTC](https://discourse.julialang.org/t/extracting-all-struct-fields/36115/8 "2020-03-18T15:03:19Z")

</div>

> [@francesco.alemanno](#):
>
> it is ugly as hell and it leaks in the main module, what can i do?

One option is to go in a different way and interpolate the struct fields into the body. This can maybe serve as inspiration:

```julia
macro with(declaration, expr)
    return esc(with_func(declaration, expr))
end

function with_func(declaration, expr)
    @assert declaration.head == :(::)
    v, typ = declaration.args
    fields = fieldnames(getfield(@ __MODULE__ , typ))
    expr = recursive_interpolation(expr, fields, v)
    return expr
end

function recursive_interpolation(expr::Expr, fields, v)
    return Expr(expr.head, recursive_interpolation.(expr.args, Ref(fields), v)...)
end

function recursive_interpolation(s::Symbol, fields, v)
    if s in fields
        return :($(v).$(s))
    end
    return s
end

recursive_interpolation(expr, fields, v) = expr

struct My
    a
    b
end

a = My(2, 3)

function f(x)
    @with x::My begin
        return a + 2b
    end
end

f(a)

```

Disclaimer: I’m not entirely sure that `@ __MODULE__ ` does the right thing in all circumstances.
