# Eltype and dimensions from function definition

I would like to use a matrix function as basis for defining more complex structures. For this, I need to determine cheaply the `eltype` of the result and the dimensions. To be concrete, I have a matrix function defined as

``````julia> a(t) = [cos(t) sin(t); 1 -1]
a (generic function with 1 method)
``````

and I would like to find out `eltype(a(t))` and `size(a(t))` without evaluating `a(t)` for a certain real value of` t`. Is this somehow possible?

If `t` is a subtype of `Real` and `a(t)` evaluates a trigonometric function then the resulting matrix will have entries that are a subtype of `AbstractFloat`, and the specific `eltype(a(t))` ought to be the same as `typeof(float(t))`.
When you are asking about size(a(t)), if you do not know about `a(t)` then you do not know about it.

1 Like

Thanks. I thought that since `a(t)` evaluates to a 2x2 matrix, this information is somehow coded in the definition of the function `a(t)`. So, my hope was to have a way to extract this information somehow.

Normal functions don’t have return types in Julia, the return type is just the type of whatever is returned.

Maybe there’s a package that makes something like this, you could even define it yourself:

``````struct TypedFunction{T} <: Function
f
end

(f::TypedFunction)(args...) = f.f(args...)

return_type(::TypedFunction{T}) where {T} = T

f = TypedFunction{Float64}(sin)
``````

But I’m not sure how much benefit there is to be extracted from doing this.

2 Likes

I like that (although I’m not sure I’d use it). Examples (showing why there probably is no builtin solution to OP’s question and showing how `TypedFunction` could increase type stability

``````a(t) = t < 0 ? [1, 2] : [1 2]
@show a(-1), typeof(a(-1))
@show a(1), typeof(a(1))

struct TypedFunction{T} <: Function
f
end

(f::TypedFunction{T})(args...) where T = convert(T, f.f(args...))

return_type(::TypedFunction{T}) where {T} = T

ta = TypedFunction{Vector{Float64}}(a)
@show ta(-1)
@show ta(1)
``````

yielding

``````(a(-1), typeof(a(-1))) = ([1, 2], Vector{Int64})
(a(1), typeof(a(1))) = ([1 2], Matrix{Int64})
ta(-1) = [1.0, 2.0]
ERROR: MethodError: no method matching Vector{Float64}(::Matrix{Int64})
``````
1 Like
``````julia> Base.return_types(a, (Float64,))
1-element Vector{Any}:
Matrix{Float64} (alias for Array{Float64, 2})
``````

Note that `Base.return_types` is an internal function so use at your own risk.

3 Likes

Actually, I could reformulate my question to matrices which have constant dimensions. In my case, they are also periodic of a known period `T`, i.e.,
`a(t) = a(t+T)` .