# Add lines of code in a struct definition

**URL:** <https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297>\
**Category:** General Usage\
**Created:** [July 18, 2020, 5:40pm UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297 "2020-07-18T17:40:50Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![Deduction42](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/deduction42/32/9206_2.png) [@Deduction42](https://discourse.julialang.org/u/Deduction42)\
**Post date:** [July 18, 2020, 5:40pm UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/1 "2020-07-18T17:40:50Z")

</div>

I have a way to generate a list of strings of lines of code I want to add in a struct. For example, let us say I generated a vector of strings:

```julia
FieldDefinitions = ["A :: Float64", "B :: Int64"]

```

How would I go about adding these lines into a struct definition? Say, making a macro like @insert\_lines() which could be used as

```julia
struct MyNewStruct
    @insert_lines(FieldDefinitions)
end

```

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [July 18, 2020, 8:27pm UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/2 "2020-07-18T20:27:02Z")

</div>

You probably can write a macro to do that, maybe it need to take the name of the struct and output all the struct in top level. However, I have a very hard time seeing a case this is the most sensible thing to do.

---

<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:** [July 18, 2020, 8:28pm UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/3 "2020-07-18T20:28:25Z")

</div>

Since macros are evaluated at compile time, it’s a little hard to imagine a place that this would be useful. If you want this so a number of times can all have the same few fields, I would just bundle those fields into a struct and have your typed have one of those. That said, I think this is possible.

---

<div class="post-metadata">

**Author:** ![Deduction42](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/deduction42/32/9206_2.png) [@Deduction42](https://discourse.julialang.org/u/Deduction42)\
**Post date:** [July 18, 2020, 8:38pm UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/4 "2020-07-18T20:38:04Z")

</div>

Basically, I’m trying to organize a simulation for a bunch of different industrial pieces of equipment. For example, a generic pump will have a number of fields common to all, but some specific types will differ (the system has a piston pump and a centrifugal one). If I’m going to look for a flow rate, I want it to be at the top level and not have to go 3 levels down the struct hierarchy to do it. I could copy/paste all the fields but I don’t want to do that. I just want to “inherit” most of the parent’s fields (but not all, so I can’t do simple inheritance in that case).

---

<div class="post-metadata">

**Author:** ![Deduction42](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/deduction42/32/9206_2.png) [@Deduction42](https://discourse.julialang.org/u/Deduction42)\
**Post date:** [July 19, 2020, 12:20am UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/5 "2020-07-19T00:20:29Z")

</div>

I basically made it work. I used a macro generates a list of fields and a list of types (all in String Array format). I then used

```julia
     CodeLines = join(FieldList .* " :: " .* TypeList, " ; ")
     return esc(Meta.parse("begin $CodeLines end"))

```

I have no idea why I needed the “begin” and “end” for the Meta.parse command. While it’s frustrating to not know why your code dosen’t work, it’s also frustrating to get it working and not know why…

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [July 19, 2020, 12:31am UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/6 "2020-07-19T00:31:45Z")

</div>

Perhaps this may be helpful?  
[https://github.com/PetrKryslUCSD/FinEtools.jl/blob/423f8d168b286ebbb16c59196268dd4250f31e95/src/FESetModule.jl#L55](https://github.com/PetrKryslUCSD/FinEtools.jl/blob/423f8d168b286ebbb16c59196268dd4250f31e95/src/FESetModule.jl#L55)

---

<div class="post-metadata">

**Author:** ![Deduction42](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/deduction42/32/9206_2.png) [@Deduction42](https://discourse.julialang.org/u/Deduction42)\
**Post date:** [July 19, 2020, 2:39pm UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/7 "2020-07-19T14:39:57Z")

</div>

Actually, I ended up seeing something similar to that which helped me. Basically the macro that inserted the lines used the form

```julia
macro add_some_fields()
    return esc(:(A::Int64; B::Float64))
end

```

Which worked as expected. The only problem is that my macro produced the fields and the types by looking at a parent object that was an input. Now let us say I wanted to create a pump type CentrifugalPump\_Type and inherit all the fields from GenericPump\_Type some exceptions (such as specifications). I would have to generate a string representing that code and then parse it. When I used the following command:

```julia
InnerExp = :(
    A::Int64;
    B::Float64; )

```

I would get

```julia
quote
    A::Int64
    #= none:1 =#
    B::Float64
end

```

I tried using

```julia
CodeLines = "A::Int64; B::Float64"
InnerExp = Meta.parse("quote $CodeLines end")
>>
:($(Expr(:quote, quote
    #= none:1 =#
    A::Int64
    #= none:1 =#
    B::Float64
end)))

```

This was not the result I expected, but buried somewhere in the internet, I found someone suggesting a begin … end statement. So I tried this

```julia
InnerExp = Meta.parse("begin $CodeLines end")
quote
    #= none:1 =#
    A::Int64
    #= none:1 =#
    B::Float64
end

```

Which yielded the same result as ` :( A::Int64; B::Float64; )`. So I guess putting multiple lines in an expression is implicitly assuming a “begin…end” statement. This is what ended up working in the simple macro.

```julia
macro add_some_fields()
    CodeLines = "A::Int64; B::Float64"
    return esc(Meta.parse("begin $CodeLines end"))
end

```

Now that CodeLines are strings, I can very easily generate any kind of code that I want.

---

<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:** [July 19, 2020, 6:37pm UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/8 "2020-07-19T18:37:18Z")

</div>

It should never be necessary to manipulate Julia code as strings–doing so introduces lots of annoying edge cases and parsing issues, as you’ve just discovered. In your case, you can skip all of the parsing and the manual `begin` and `end` splicing by just _writing an expression directly_:

```julia
julia> CodeLines = :(A::Int64; B::Float64)
quote
    A::Int64
    #= REPL[35]:1 =#
    B::Float64
end

julia> @eval struct Foo
         $CodeLines
       end

julia> f = Foo(1, 2)
Foo(1, 2.0)

julia> f.A
1

julia> f.B
2.0

```

No `parse`, no `begin`, no string interpolation, just working code with less typing!

This is a really important rule of thumb in Julia metaprogramming: Use expressions; don’t use strings.

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [July 19, 2020, 8:02pm UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/9 "2020-07-19T20:02:22Z")

</div>

So let us say I have a type whose fields I want to duplicate in another type. I came up with this:

```julia
struct P
    a::Int64
    b::Float64
end

dump(:(struct P
    a::Int64
    b::Float64
end))

macro duplf(P)
    ex = Expr(:block)
    return quote
        global ex = Expr(:block)
        for (n,t) in zip(fieldnames($P), fieldtypes($P))
            global n, t
            global ex
            push!(ex.args, LineNumberNode(0, ""))
            push!(ex.args, Expr(:(::), Symbol(n), Symbol(t)))
        end
        ex
    end
end

dump(@duplf(P))

struct OP
    @duplf(P)
end

```

Unfortunately, even though the macro `duplf` returns an expression which matches the definition of the fields of the type `P`, the definition of the type `OP` does not work and there are no fields in that structure. I must be missing something.

---

<div class="post-metadata">

**Author:** ![Deduction42](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/deduction42/32/9206_2.png) [@Deduction42](https://discourse.julialang.org/u/Deduction42)\
**Post date:** [July 19, 2020, 8:48pm UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/10 "2020-07-19T20:48:21Z")

</div>

It gets really hard to use expressions for what I’m doing, especially once the types have a parameter in them (my types are basically like arrays, that can have strings, floats, or even complex and dual numbers). I basically got something like this working

```julia
macro inherit_asset_fields(ParType_S::Symbol, T::Symbol)
    ParType = eval(ParType_S)

    #Exclude "Specs" from the duplication, specific to "Asset" inheritance
    IndKeep = findall(x-> x != :Specs, fieldnames(ParType))

    #Creates an arbitrary sentinel type to recover parameterization
    SentinelType = Some{T}

    #Get the fields lists and types (with sentinel types)
    FieldList = string.( fieldnames(ParType)[IndKeep] )
    TypeList = string.( fieldtypes(ParType{SentinelType})[IndKeep] )

    #Recover the parameterization through the sentinel type
    TypeList = replace.(TypeList, string(SentinelType)=>string(T) ) #

    CodeLines = join(FieldList .* " :: " .* TypeList, " ; ")
    return esc(Meta.parse("begin $CodeLines end"))
end

mutable struct MyOldType{T}
    Name :: Symbol
    A :: T
    B :: T
    V :: Vector{T}
    Specs :: String
end

mutable struct MyNewType{T} 
    @inherit_asset_fields(MyOldType, T)
    C :: T
    NewSpecs::String
end

```

I know this is inelegant, but I’m not sure where I start in terms of learning how to use expressions effectively, or how I go about recovering parameters from fieldtypes(MyOldType) without some dumb hack like creating Some{:T} and doing a string replace on it. If I try using fieldtypes(MyOldType), I just get “Any” where T could be. The problem is, the actual struct might actually include a field of type “Any” (I’ll try to avoid it, but it might end up happening somehow, even by accident).

---

<div class="post-metadata">

**Author:** ![greg\_plowman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/greg_plowman/32/8100_2.png) [@greg\_plowman](https://discourse.julialang.org/u/greg_plowman)\
**Post date:** [July 19, 2020, 9:41pm UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/11 "2020-07-19T21:41:48Z")

</div>

> [@PetrKryslUCSD](#):
>
> Unfortunately, even though the macro `duplf` returns an expression which matches the definition of the fields of the type `P` , the definition of the type `OP` does not work and there are no fields in that structure. I must be missing something.

This seems to work:

```julia
macro dup_fields(T)
    structType = Core.eval( __module__ , T)
    ex = Expr(:block)
    for fieldName in fieldnames(structType)
        fieldType = fieldtype(structType, fieldName)
        push!(ex.args, Expr(:(::), fieldName, Symbol(fieldType)))
    end
    return esc(ex)
end

```

I’m not really happy about the `eval`, but not sure how to get around this?

```julia
struct P
    a::Int64
    b::Float64
end

struct Q
    @dup_fields(P)
end

dump(P)
dump(Q)

```

---

<div class="post-metadata">

**Author:** ![Deduction42](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/deduction42/32/9206_2.png) [@Deduction42](https://discourse.julialang.org/u/Deduction42)\
**Post date:** [July 19, 2020, 10:43pm UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/12 "2020-07-19T22:43:41Z")

</div>

I don’t think there is a way to get around the eval. Without the “eval”, the macro doesn’t even know if the type exists yet so it can’t execute “fieldnames” if it can’t be evaluated at the module level; it needs to already exist in the module. Anyway, your code nearly worked in my case. I modified it to suit mine

```julia
macro inherit_asset_fields(AssetType_S, T)

    BaseAssetType = Core.eval( __module__ , AssetType_S)
    AssetType = BaseAssetType{T}
    ex = Expr(:block)

    for fName in filter( x-> x!=:Specs, fieldnames(AssetType) )
        fType = fieldtype(AssetType, fName)
        push!(ex.args, Expr(:(::), fName, fType))
    end

    return esc(ex)
end

mutable struct MyOldType{T}
    Name :: Symbol
    A :: T
    B :: T
    V :: Vector{T}
    Specs :: String
end

mutable struct MyNewType{T}
    @inherit_asset_fields(MyOldType, T)
    C :: T
    NewSpecs::String
end

```

It ALMOST works, however, it gets stuck on `Vector{T}`. It actually tries to put in `Vector{:T}` when it should actually put in `Vector{T}`. I’m not sure how to get the symbol `:T` to be converted to just `T` in the push! Expr statement without converting fType into a string and doing a search/replace on a sentinel type. In every other instance it gets handled automatically and gracefully without string conversion.

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [July 20, 2020, 12:24am UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/13 "2020-07-20T00:24:18Z")

</div>

Right, the `quote` needed for the interpolation is the problem.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 20, 2020, 6:04am UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/14 "2020-07-20T06:04:54Z")

</div>

> [@Deduction42](#):
>
> a generic pump will have a number of fields common to all, but some specific types will differ

Use composition (search for “composition over inheritance”).

Trying to replicate what inheritance does is fighting the language.

---

<div class="post-metadata">

**Author:** ![Deduction42](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/deduction42/32/9206_2.png) [@Deduction42](https://discourse.julialang.org/u/Deduction42)\
**Post date:** [July 20, 2020, 3:43pm UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/15 "2020-07-20T15:43:44Z")

</div>

Okay, I think I found the root of this problem. If I try to get an instance of a type by using

```julia
MyOldType{:T}

```

I will get for field `:V`

```julia
Vector{:T}

```

Which is actually a `Vector` with the type parameter `:T`. However, what I actually want to do is convert this “Type” into an “Expression” of `Vector` with an argument `T`. Converting this type into a string and re-parsing it will correctly reinterpret this as an expression. Is there any way to do this without such a dumb hack?

---

<div class="post-metadata">

**Author:** ![Deduction42](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/deduction42/32/9206_2.png) [@Deduction42](https://discourse.julialang.org/u/Deduction42)\
**Post date:** [July 20, 2020, 5:41pm UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/16 "2020-07-20T17:41:47Z")

</div>

Okay! I managed to find a remarkably clean way to do this!! I’ve also seen other threads of people who want to do something similar (and it turns out there is a Mixers.jl package that can be used to do what it is that I’m doing, but in my opinion, this method looks more intuitive). Anyway, the key step was to infer whether the FieldType was a Symbol, a non-parametric type or a parametric type. I also learned I could get the actual constructer of a type from the “.name.wrapper” field and get the parameters from the “.parameter” field too. Once this “get\_type\_expression” function worked, everything else fell into place.

```julia
function get_type_expression(X::Union{Symbol,DataType})
    if X isa Symbol
        return X
    elseif X isa DataType
        Params = X.parameters
        if isempty(Params)
            return Symbol(X.name.wrapper)
        else
            return Expr(:curly, Symbol(X.name.wrapper), Params...)
        end
    end
end

macro inherit_asset_fields(AssetTypeExp::Expr)
    BaseAssetType = Core.eval(@ __MODULE__ , AssetTypeExp.args[1])
    TypeSymbols = AssetTypeExp.args[2:end]
    AssetType = BaseAssetType{TypeSymbols...}

    ex = Expr(:block)
    for fName in filter( x-> x!=:Specs, fieldnames(AssetType) )
        fType = fieldtype(AssetType, fName)
        fTypeParsed = get_type_expression(fType)
        push!(ex.args, :( $fName :: $fTypeParsed ) )
    end

    return esc(ex)
end

mutable struct MyOldType{T}
    Name :: Symbol
    A :: T
    B :: T
    V :: Vector{T}
    Specs :: String
end

mutable struct MyNewType{T}
    @inherit_asset_fields(MyOldType{T})
    C :: T
    NewSpecs::String
end

```

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [July 20, 2020, 5:42pm UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/17 "2020-07-20T17:42:15Z")

</div>

OP I think you may be missing the forest for the trees a bit here. I think the solution to your problem is to _not_ use `getproperty` to access fields but rather to define functions that retrieve nested parameters. Something like the following

```julia
julia> struct IntersectType{T}
       x1::T
       x2::T
       end

julia> abstract type SpecificType end

julia> struct SpecificType1 <: SpecificType
       i::IntersectType
       y1
       end

julia> struct SpecificType2 <: SpecificType
       i::IntersectType
       y2
       end

julia> function x1(s::SpecificType)
       s.i.x1
       end
x1 (generic function with 1 method)

julia> function x2(s::SpecificType)
       s.i.x2
       end
x2 (generic function with 1 method)

```

So you have an `IntersectType` that stores the intersection of all parameters. Then you have a variety of structs part of the same abstract type.

Then for each shared parameters, you create a function that retrieves the nested parameters.

It should be feasible to do this programmatically using a strategy similar to what we use for `Missing` [here](https://github.com/JuliaLang/julia/blob/e6f13e967a5b1289244fb48680b0bd434b4faa9f/base/missing.jl#L93).

EDIT: I should add that in general, replacing `getproperty` calls with functions is generally considered good programming style, as it means you don’t have to expose the internals of your structs to the user.

---

<div class="post-metadata">

**Author:** ![Deduction42](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/deduction42/32/9206_2.png) [@Deduction42](https://discourse.julialang.org/u/Deduction42)\
**Post date:** [July 20, 2020, 7:40pm UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/18 "2020-07-20T19:40:47Z")

</div>

I actually thought about doing it this way, but in the end, I realized that the actual structure is informative of the object. There are two hierarchical relationships that are going on, one is taxonomic and the other is componential, so using composition becomes confusing as it convolutes the intent behind the object’s structure. Also, since this is a simulation with all the internals having physical significance, I actually WANT to expose all the internals to the user.

It turns out that multiple dispatch really helps here when I want to predict the behaviors of two different kinds of pumps. I can mix and match any analysis tools I want in a larger function as long as I know it has all the appropriate fields. Trying to call one analysis package on a “parent” type would work in almost all cases, but I found a couple where such a paradigm would end up being too restrictive. Julia really saved my figurative butt here. I’d be very hard pressed to implement this in a pure OOP paradigm.

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [July 20, 2020, 7:45pm UTC](https://discourse.julialang.org/t/add-lines-of-code-in-a-struct-definition/43297/19 "2020-07-20T19:45:29Z")

</div>

> [@Deduction42](#):
>
> Trying to call one analysis package on a “parent” type would work in almost all cases, but I found a couple where such a paradigm would end up being too restrictive. Julia really saved my figurative butt here. I’d be very hard pressed to implement this in a pure OOP paradigm.

You can have nested abstract types, if a few cases are too restrictive you can always define more abstract or concrete types to allow for special behavior.
