I’m starting to wade into the wonderful world of SnoopCompile and the many insights it gives (and realising along the way that my understanding of types, inference etc, is shallow to say the least). One thing I got from reading the docs (and getting excellent comments by @tim.holy) was that it’s better, where possible, to use concrete types to reduce the time to first call.
In my code, I often have to repeatedly work on sections of arrays: either a subset of a String or a subset of a Vector say to simplify a Vector{Int}
. Intuitively, it seemed to me to be a good idea to not create new objects for these, so I often basically do:
subset = SubString(original_string, range)
do_thing(subset)
and the same with @view
of vectors. This is often in a recursive function so the signature of do_thing
in my code is typically something like:
do_thing(obj::Union{SubString{String}, String})
or
do_thing(obj::AbstractVector{Int})
but these are not concrete types and from a discussion with @tim.holy ; I believe that this is not ideal.
My question is then, am I better off making the original objects into a sub-version of themselves before processing them? i.e.:
processed_original_string = SubString(original_string)
do_thing(processed_original_string)
and
processed_original_array = @view original_array[eachindex(original_array)]
do_thing(processed_original_array)
?
A subsidiary question is about returned types, does concreteness matter here as well? For instance let’s say I have a function which returns a vector with objects of type either A
or B
or both, does something like:
return_vector(args)::Vector{Union{A,B}}
cause issues? Thanks a lot!