Type Inference

I always held automatic type inference as one of Julia’s distinguishing features. Why are packages full of type qualifications? Is it the performance improvement, error handling or just the coolness factor?

P.S.
I hope Julia programs do not start looking like C++ in terms of readability.

mostly not (there are only specific situations where type annotations - in functions - may improve performance). Types in declarations of structs are important, though.

This is probably the most common use. Sometimes the code gets clearer to use and debug with type annotations. Also for dispatch, when the type annotations define to which type of variable each method works (actually this is the most important use).

But to actually understand your question, maybe you would like to post some example, so a more precise answer of why annotations were used in some specific case.

1 Like

I would say neither of these.

Types in method arguments are used to say what set of arguments should dispatch to that method:

struct Cat end
struct Dog end

noise(::Cat) = "mjau"
noise(::Dog) = "woof"

So if we have a noise(Cat()) it dispatches to one method while a noise(Dog()) dispatches to another. T

JuliaCon 2019 | The Unreasonable Effectiveness of Multiple Dispatch | Stefan Karpinski - YouTube might be interesting to watch for you.

7 Likes

For example, this is from StatsBase.jl

function _momentk(v::RealArray, k::Int, m::Real)
    n = length(v)
    s = 0.0
    for i = 1:n
        @inbounds z = v[i] - m
        s += (z ^ k)
    end
    s / n
end

RealArray is an abstract type defined by the package. Is there a reason other than error handling to not write the function as:

function momentk(v, k, m)
    n = length(v)
    s = 0.0
    for i = 1:n
        @inbounds z = v[i] - m
        s += (z ^ k)
    end
    s / n
end

Of course, if i pass a vector of Complex numbers the second function happily returns a value, while the first throws up a “generic” error:

_momentk(ans,2,0)
ERROR: MethodError: no method matching _momentk(::Vector{Complex{Int64}}, ::Int64, ::Int64)
Closest candidates are:
  _momentk(::AbstractArray{T} where T<:Real, ::Int64, ::Real) at ~/play/jl/type.jl:3
Stacktrace:
 [1] top-level scope
   @ REPL[22]:1

Perhaps type annotation here precludes a more graceful handling of error (or any handling of error other than “method does not exist”?).

Thanks for the reference to the excellent talk.

I had in mind examples as such as the StatsBase one i posted above.

Just guessing, but I think it constrains to Real and Int because other types (complex and non-integer correspondingly) may technically work, but are unlikely to yield correct results.
A simpler example would be abs(x) = sqrt(x^2): this function “works” when passed complex numbers, but the result is nonsensical.

Yes, it seems to be a form of error handling. The error for complex input (above) does not say complex values are nonsensical; it says that the method signature does not match. There is a difference here i think.