# Initialize a struct without a type-parameterized field and add the field later

**URL:** <https://discourse.julialang.org/t/initialize-a-struct-without-a-type-parameterized-field-and-add-the-field-later/8814>\
**Category:** General Usage\
**Created:** [February 4, 2018, 5:19pm UTC](https://discourse.julialang.org/t/initialize-a-struct-without-a-type-parameterized-field-and-add-the-field-later/8814 "2018-02-04T17:19:01Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)\
**Post date:** [February 4, 2018, 5:19pm UTC](https://discourse.julialang.org/t/initialize-a-struct-without-a-type-parameterized-field-and-add-the-field-later/8814/1 "2018-02-04T17:19:01Z")

</div>

I am trying to do something that may, or may not be possible. I want to use ForwardDiff, and create a Jacobian function. This function will be part of a `struct`. A parameter container is also part of this `struct`. Now, I want the Jacobian function to close over the entire `struct`, not just the parameter container. A short description of that is present here: [https://github.com/JuliaDiff/ForwardDiff.jl/issues/296](https://github.com/JuliaDiff/ForwardDiff.jl/issues/296)

Unfortuantely, I do not know how to do it. At the moment here is my try:

```julia
# Here f must be of the form: f(x) -> SVector (ONE ARGUMENT!)
function generate_jacobian_oop(f::F, x::X) where {F, X}
    # Test f structure:
    L = length(x)
    y = f(x)
    @assert typeof(y) <: SVector
    @assert length(y) == L
    # Setup config
    cfg = ForwardDiff.JacobianConfig(f, x)
    FDjac(x, p) = ForwardDiff.jacobian(f, x, cfg)
    return FDjac
end

mutable struct DiscreteDS{D, T<:Number, F, P, J}
    state::SVector{D,T}
    eom::F
    p::P
    jacob::J
    function DiscreteDS{D, T, F, P}(state::SVector{D,T}, eom::F, p::P) where {D, T, F, P}
       f = new(state, eom, p)
       reducedeom = (x) -> eom(x, f.p)
       f.jacob = generate_jacobian_oop(reducedeom, state)
       return f
   end
end

function DiscreteDS(state::SVector{D,T}, eom::F, p::P) where {D, T, F, P}
    return DiscreteDS{D, T, F, P}(state, eom, p)
end

@inline henon_eom(x, p) = SVector{2}(1.0 - p[1]*x[1]^2 + x[2], p[2]*x[1])
p = [1.4, 0.3]

ds = DiscreteDS(SVector(0.0, 0.0), henon_eom, p)

```

This doesn’t run at the moment, because it tells me that there are too few parameters specified in `new`.

But more importantly, I also do not know how to enforce the type parameter in the line `f.jacob = generate_jacobian_oop(reducedeom, state)`…

Any help would be greatly appreciated!

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [February 4, 2018, 5:30pm UTC](https://discourse.julialang.org/t/initialize-a-struct-without-a-type-parameterized-field-and-add-the-field-later/8814/2 "2018-02-04T17:30:29Z")

</div>

Just create `jacob` before `new`?

---

<div class="post-metadata">

**Author:** ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)\
**Post date:** [February 4, 2018, 5:31pm UTC](https://discourse.julialang.org/t/initialize-a-struct-without-a-type-parameterized-field-and-add-the-field-later/8814/3 "2018-02-04T17:31:08Z")

</div>

How can I then close it over `f.p`, where `f` comes from `new`?

---

<div class="post-metadata">

**Author:** ![Datseris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/datseris/32/13406_2.png) [@Datseris](https://discourse.julialang.org/u/Datseris)\
**Post date:** [February 4, 2018, 5:33pm UTC](https://discourse.julialang.org/t/initialize-a-struct-without-a-type-parameterized-field-and-add-the-field-later/8814/4 "2018-02-04T17:33:19Z")

</div>

UPDATE: I have managed to do this using 2 different structs. I would like to avoid this if possible, but it is a last resort:

```julia
mutable struct DiscreteLaw{D, T, F, P}
    state::SVector{D,T}
    eom::F
    p::P
end

mutable struct DiscreteDS{D, T, F, P, J}
    system::DiscreteLaw{D, T, F, P}
    jacobian::J
end

function DiscreteDS(state::SVector{D,T}, eom::F, p::P) where {D, T, F, P}
    system = DiscreteLaw(state, eom, p)
    reducedeom = (x) -> eom(x, system.p)
    jacob = generate_jacobian_oop(reducedeom, state)
    return DiscreteDS(system, jacob)
end

@inline henon_eom(x, p) = SVector{2}(1.0 - p[1]*x[1]^2 + x[2], p[2]*x[1])
p = [1.4, 0.3]

ds = DiscreteDS(SVector(0.0, 0.0), henon_eom, p)

```
