Hi there, I’m a bit new to Julia, and I can’t seem to figure out how to make my code type-stable. I’m writing some code in the context of feature selection, and the specific function I’m looking at now is meant to create formulas for all predicted variables (ys
), given a set of selected right-hand-side variables (rhs
). Here is the code:
using StatsModels
function compose(y::Symbol, terms::Vector{Symbol})::FormulaTerm
return term(y) ~ foldl(+, term.(terms))
end
function get_formulas(ys::Vector{Symbol}, rhs::Vector{Symbol})::Vector{FormulaTerm}
return map(y::Symbol -> compose(y, rhs), ys)
end
Despite the fixed return type of the compose
function and the flawless ‘conversion’ of the map
result to the fixed return type of the get_formulas
function, the compiler does not think the return type of the map
call is stable. Here is the output by @code_warntype
:
julia> @code_warntype get_formulas([:y1, :y2], [:x1, :x2])
Variables
#self#::Core.Const(get_formulas)
ys::Vector{Symbol}
rhs::Vector{Symbol}
#13::var"#13#14"{Vector{Symbol}}
Body::Vector{FormulaTerm}
1 ─ %1 = Core.apply_type(Main.Vector, Main.FormulaTerm)::Core.Const(Vector{FormulaTerm})
│ %2 = Main.:(var"#13#14")::Core.Const(var"#13#14")
│ %3 = Core.typeof(rhs)::Core.Const(Vector{Symbol})
│ %4 = Core.apply_type(%2, %3)::Core.Const(var"#13#14"{Vector{Symbol}})
│ (#13 = %new(%4, rhs))
│ %6 = #13::var"#13#14"{Vector{Symbol}}
│ %7 = Main.map(%6, ys)::Vector{_A} where _A
│ %8 = Base.convert(%1, %7)::Any
│ %9 = Core.typeassert(%8, %1)::Vector{FormulaTerm}
└── return %9
where ::Vector{_A} where _A
(at %7
) and ::Any
(at %8
) are colored red.
Could anyone point me in the direction of type stability?
Things I’ve already tried:
- I tried simply adding
::Vector{FormulaTerm}
after themap
call, but that results in an error:
TypeError: in typeassert, expected Vector{FormulaTerm}, got a value of type Vector{FormulaTerm{Term, Tuple{Term, Term}}}
- Changing that type assert to
::Vector{F} where F<: FormulaTerm
gets rid of the error, but does not get rid of the type instability.