Consider two simple functions that take one Float64
and return another Float64
:
julia> f(x) = x^2
f (generic function with 1 method)
julia> g(x) = x^3
g (generic function with 1 method)
Also, consider a higher-order function that takes a function and returns another function:
julia> h(fun::Function) = x -> 2fun(x)
h (generic function with 1 method)
julia> h(f)(2.)
8.0
julia> h(g)(2.)
16.0
Now, I want to apply h
to an array of functions. However, such operation’s type stability depends on whether the array is homogeneous or not:
julia> fun_homog = [g, g]
2-element Array{#g,1}:
g
g
julia> fun_inhomog = [g, h]
2-element Array{Function,1}:
g
h
julia> @code_warntype broadcast(h, fun_homog)
(No instability)
julia> @code_warntype broadcast(h, fun_inhomog)
(Lots of instability)
The point here is that fun_homog
’s element type is #g
, whereas fun_inhomog
’s element type is abstract Function
.
I wonder if this kind of instability can be eliminated by allowing function type specification (like C’s function pointer). Clearly, f
and g
here are of the same type, in the sense that both take one Float64
and return another Float64
. However, currently once an array [f, g]
is formed, the array does not recognize such similarity between f
and g
.
In other words, I wonder if the array [f, g]
can be typed as something like Array[::Function(::Float64)::Float64]
to indicate that the array’s elements are functions that take one Float64
and return another Float64
, and also wonder if such information could be used to eliminate the aforementioned type instability.