But it gives me this error, and I can’t see why it should be a problem:
ERROR: TypeError: in keyword argument temps, expected Vector{Number}, got a value of type Vector{Int64}
When getting errors, it is best to read carefully and assume the details are correct, even if the reason is still not clear.
In this case, temps is indeed a Vector{Int64} and a Vector{Number} is expected as specified in the definition. As evidence:
julia> typeof( [0] )
Vector{Int64} (alias for Array{Int64, 1})
whereas
julia> typeof( Number[0] )
Vector{Number} (alias for Array{Number, 1})
Perhaps the function definition should go with temps::Vector{<:Number} which matches Vector{Int64} too.
Better still, the typing of parameters is not mandatory in Julia and it is usually cleaner to just drop them and let the compiler infer and compile the correct version of a function. For example, dropping all parameter types:
function runCommands(;programName="simulation", dt=0.01, T=2, temps, N, sizeArr)
cmdStrings = map((temp, size) -> `./$programName dt=$(dt)_T=$(T)_temp=$(temp)_N=$(N)_size=$(size)`, temps, sizeArr)
map(run, cmdStrings)
end
Thanks, the subtype declaration solved the issue, but why does Julia care if it is Vector{Int64} and not Vector{Number}? Why is there an explicit need for this when x::Number can readily accept any subtypes anyway?
This is connected to the way the type system in Julia has been defined (since forever) and it is actually quite a good thing. Specifically: Vector{Int64} is NOT a subtype of Vector{Number}. This property is sometimes called invariant-parametric types. The best thing is to read up on it in the docs: https://docs.julialang.org/en/v1/manual/types/#man-parametric-composite-types
In short, Number is an abstract type of no definite size. A Vector{Number} is therefore stored as a collection of pointers to whatever Numbers are put in there. On the other hand, an Int64 is a concrete type of size 8 bytes. A Vector{Int64} is therefore a contiguous chunk of memory of 8-byte integers. This enables the compiler to generate much more efficient code.
Specifying a formal argument as Vector{Number} requires the actual argument to be just that, a collection of pointers to various types of Numbers. Specifying it as Vector{<:Number} means that the actual argument can be a Vector of any number type, in particular a Vector{Int64}. The function will be compiled for the actual argument, i.e. there will be a compiled version for Vector{Int64} as well as a compiled version for Vector{Float16} (if you ever call the function with such thing).
It would be possible to let Vector{Number} mean a vector of any number type, i.e. having covariant type parameters, and the parameters work like that for the types Union and Tuple. There are drawbacks and benefits with everything, but julia has always had invariant type parameters (except for Union and Tuple).
The way I think of it is that a Vector{Number} is a Vector that can accept and store a number of any type, while Vector{Int64} can only store Int64. Therefore they cannot be the same. On the other hand x::Number can be any type of number.