Excellent, thank you for the quick and helpful responses.
One more related question.
If I were to define a function that could either on an Array{T} where T <:
Number or on T itself, is there any reason not to do this:
typealias ScalarOrArray{T} Union(T, Array{T})
function bar{T}(x::ScalarOrArray{T}, y::ScalarOrArray{T}) = x+y
My real question is would there be performance penalties for using Union in
this way?
Would it help the compiler at all to define this as
function bar{T}(x::Array{T}, y::Array{T}) = x+y
function bar{T}(x::Array{T}, y::T) = x+y
function bar{T}(x::T, y::Array{T}) = x+y
function bar{T}(x::T, y::T) = x+y
?
On Tuesday, August 19, 2014 11:45:10 AM UTC-7, Johan Sigfrids wrote:
Performance wise it makes no difference. The JIT will produce the same code
> for all three:
>
> foo1(x::Real, y::Real) = x + y
>
> foo2{ T<: Real}(x::T, y::T) = x + y
>
> foo3{T <: Real, S <: Real}(x::T, y::S) = x + y
>
> You can verify it by running @code_native on all of them. They will all
> result in the same machine code for the same input types.
>
> @code_native foo1(1, 1)
>
> .text
> Filename: none
> Source line: 1
> push RBP
> mov RBP, RSP
> Source line: 1
> add RCX, RDX
> mov RAX, RCX
> pop RBP
> ret
>
>
> The one difference is that foo2 requires both x and y to be of the same
> type:
>
> foo2(1, 1.0)
>
> `foo2` has no method matching foo2(::Int64, ::Float64)
>
>
> You can mix and match Real types with foo1 and foo3.
>
> On Tuesday, August 19, 2014 9:30:42 PM UTC+3, Spencer Lyon wrote:
>>
>> Suppose I am defining a function that operates on any two real numbers.
>> Which of the following ways of specifying types is preferred (in terms of
>> idomatic Julia and performance considerations) and why?
>>
>> ```julia
>>
>> function foo1(x::Real, y::Real) = ...
>>
>> function foo2{ T<: Real}(x::T, y::T) = ...
>>
>> function foo3{T <: Real, S <: Real}(x::T, y::S) = ...
>> ```
>>
>>