# How to avoid type instability in the return type of my function?

I have a struct and a simple function:

``````struct SU2Element <: AbstractMatrix{ComplexF64}
t₁::ComplexF64
t₂::ComplexF64

function SU2Element(t₁::Number, t₂::Number)
SU2Element(ComplexF64(t₁), ComplexF64(t₂))
end

function SU2Element(t₁::ComplexF64, t₂::ComplexF64)
new(t₁, t₂)
end
end

``````
``````function normalizeSU2(S::SU2Element)
sqrtΔ = √det(S)
t₁ = S.t₁ / sqrtΔ
t₂ = S.t₂ / sqrtΔ
SU2Element(t₁, t₂)
end
``````

This basically takes an `SU2Element <: AbstractMatrix{Complex}` and normalizes it to have determinant 1.
In an external function, I need to construct an `SU2Element` and normalize it, but I also need `sqrtΔ` before the normalization. Since I think it is pointless to calculate `sqrtΔ` in `normalizeSU2` just to have it dropped and recalculated outside, I though of returning `sqrtΔ` from `normalizeSU2` in a tuple, like this:

``````function normalizeSU2(S::SU2Element, returndet = false)
sqrtΔ = √det(S)
t₁ = S.t₁ / sqrtΔ
t₂ = S.t₂ / sqrtΔ
if returndet
SU2Element(t₁, t₂), sqrtΔ
else
SU2Element(t₁, t₂)
end
end
``````

The problem with this approach is that it is not type stable. I know I shouldn’t optimize prematurely, but this function gets called a lot in a hot loop, and having already recognized the type instability, I though of trying to solve it.

One solution is to always return `SU2Element(t₁, t₂), sqrtΔ` and just not use `sqrtΔ` in places I don’t need it. But this seems a bit off, I would prefer for the function to return `sqrtΔ` when I’m explicit about it.

Another approach is to just have two different functions with different names, which works and it is explicit, but also knowing how powerful Julia is, I would like to at least try to find a more Julian solution.

Finally, I could pass `Val(true)` or `Val(false)` and dispatch on that, but that would require me to pass `Val(false)` every time I don’t need `sqrtΔ` which is a bit annoying.

Is there a nice way of solving this, that lets me call `normalizeSU2(S)` and have only `SU2Element` returned, and be explicit when I need `sqrtΔ`?

I would go for this. (Or just write `a, _ = f(...)` to ignore the second return value)

2 Likes

what about having 2 methods of the function, where the second one lets the caller pass in the sqrt?

2 Likes

Yeah, it’s a little awkward.

I would probably always return the determinant, and just let the caller throw it away if needs be, ie. `su2, _ = normlizeSU2(su2)`. Seems simple enough.