This is a question about efficiency. Suppose I have a routine which performs an operation in the same manner on an array irrespective of whether the entries are Int, Float or Complex. The output type will be an array with the same data-type. How can I implement that without overloading the function with different argument types ?
For example, consider the simple function

function f(a::Array{Float64,1}) ::Array{Float64,1}
for i in 1:size(a,1)
a[i]*=i;
end
end

The actual body of the funciton is not relevant, in reality it will be something more complicated. If I want this function to work for Int64 and Complex{Float64} arrays too, do I need to repeat the definition but with different argument types ? I have read in Julia’s performance enhancing tips that specifying the data type can lead to more efficient use of time and memory. IS there a trade-off ?

In many languages with optional type declarations, adding declarations is the principal way to make code run faster. This is not the case in Julia. In Julia, the compiler generally knows the types of all function arguments, local variables, and expressions.

What that means is that any of the following function definitions will give exactly the same performance:

function f1(a) # matches any `a`; equivalent to `a::Any`
...
end
function f2(a::AbstractArray) # matches an array with any number of dimensions
...
end
function f3(a::AbstractVector) # matches an array with exactly one dimension
...
end
function f4(a::AbstractVector{<: Number}) # matches an array with exactly one dimension
# whose elements are all some kind of `Number`
...
end
function f5(a::Vector{Float64}) # matches only exactly a Vector of Float64
...
end

Try it! Define each of those functions and install BenchmarkTools.jl via:

So why would you choose f4 instead of f1 ? Adding types to your function arguments is a matter of API design. If you define an f4(a::AbstractVector{<:Number}), then you can also define f4(a::SomeOtherType) and the compiler will automatically pick the appropriate method for whatever input is passed in. Or you might choose to specify your argument types as a signal to users of your code so that they know what you’re expecting them to provide.

If you mean an array with 2 elements, like [3, 4], then the answer is that you cannot restrict the length of an array like that, since the type of a standard Julia array does not contain the information about its length.

A good alternative would be to use a tuple instead:

julia> f(x, (y, z)) = x * (y + z)
f (generic function with 1 method)
julia> f(1, (2, 3))
5

What you are probably looking for here is a Tuple not an Array. The difference is that Tuples allow inference on small statically sized heterogeneous collections.