# MethodError for function calling with an argument a parametric composite type (struct)

Hi there

I have the following code, which, if necessary I might strip down.

``````using Parameters
using Unitful

@with_kw struct EosConst{T<:Real}
w_0::T = -1.0
end

@with_kw struct EosCPL{T<:Real}
w_0::T = -1
w_a::T = 0
end

Eos = Union{EosConst, EosCPL}

@with_kw struct CosmoModel{T1<:Real,T2<:Unitful.Quantity,T3<:Eos}
h_Hubble::T1 = 0.69
Ω_m0::T1 = 0.3
T_γ0::T2 = 2.75u"K"
Ω_γ0::T1 = 0.0
Ω_ν0::T1 = 0.0
Ω_r0::T1 = Ω_γ0 + Ω_ν0; @assert Ω_r0 == Ω_γ0 + Ω_ν0
Ω_n0::T1 = Ω_m0 + Ω_r0; @assert Ω_n0 == Ω_m0 + Ω_r0
Ω_exo0::T1 = 0.7
Ω_tot0::T1 = Ω_n0 + Ω_exo0; @assert Ω_tot0 == Ω_n0 + Ω_exo0
Ω_K0::T1 = 0.0; @assert Ω_K0 == 1 - Ω_tot0
eos::T3 = EosConst()
end

function E_Hubble(z; cosmo::CosmoModel)
@unpack Ω_m0, Ω_r0, Ω_exo0, Ω_K0, eos = cosmo
return sqrt(Ω_m0*(1 + z)^3 + Ω_r0*(1 + z)^4 + Ω_K0*(1 + z)^2 + Ω_exo0*(1 + z)^(3*(1 + eos.w_0)))
end
``````

When I issue the commands:

``````c = CosmoModel()
E_Hubble(0.0, c)
``````

the first one works ok, but the second one spits the following:

``````ERROR: MethodError: no method matching E_Hubble(::Float64, ::CosmoModel{Float64,Quantity{Float64,𝚯,Unitful.FreeUnits{(K,),𝚯,nothing}},EosConst{Float64}})
Closest candidates are:
E_Hubble(::Any; cosmo) at /home/orca/Dropbox/research/modified_gravity/programs/mocalvao/julia/cosmo/src/background.jl:32
Stacktrace:
 top-level scope at REPL:1
``````

What am I doing wrong?

`E_Hubble` expects `cosmo` as a keyword argument, and is getting it as a regular/positional argument instead.

2 Likes

How silly of me! Thanks a lot.

I would now like to generalize my (generic) function `E_Hubble(z, c::CosmoModel)` above, such that it has 2 distinct methods: one for the struct `EosConst`, and another for the struct `EosCPL`, which are present inside the struct `CosmoModel`, via the union’ed type `Eos`. How should I go about declaring these distinct methods, given that the direct argument of the function is a struct of type `CosmoModel`, not directly of `EosConst` or `EosCPL` ?

Another strategy is, of course, to insert an if block inside the current E_Hubble function to test, via typeof, for the 2 distinct substructs `EosConst` and `EosCPL`. In this case, I would circumvent having to define two distinct methods.

I wonder however about the differences in performance of these two approaches: (i) two methods somehow based on signature, (ii) or the last one, with just one method and an if block…

If more advisable, I can post a new topic…

Usually it’s best to start a new topic for visibility. I probably wouldn’t have seen this if I hadn’t left the window open for the rest of the day, since the topic is solved and the new question wasn’t a direct reply You could declare two separate methods based on the parameters of `CosmsoModel`, like

``````function E_Hubble(z, cosmo::CosmoModel{T1, T2, EosCPL}) where {T1, T2}
...
end
function E_Hubble(z, cosmo::CosmoModel{T1, T2, EosConst}) where {T1, T2}
...
end
``````

But it might make more sense to hand the work off to another method that dispatches directly on `Eos`, or to split the `CosmoModel` struct into smaller pieces.

1 Like

@tomerarnon Thanks. I had gathered both of your suggestions. I will try to code them, check and, if necessary, post a new topic.

1 Like