Is there any difference between defining functions with f(x::Real)
and f{T <: Real}(x::T)
?
@code_warntype
gives the same output for
function f(x::Real)
x^2
end
function g{T <: Real}(x::T)
x^2
end
The parametric type T
isn't actually used to express any relationships between types, so there's little justification for its usage, which just adds needless complexity.
Here's an example, in which using a parametric type would be necessary:
function pow{T <: Real}(base::T, exponent::T)
base^power
end
In this case, T
is necessary to enforce that both base
and exponent
have the same type, with the restriction that that type must be a subtype of Real
.
In constrast, here's the same function, without using a parametric type:
function pow(base:: Real, exponent:: Real)
base^power
end
Now this functions requires that both base
and exponent
be subtypes of Real
, but there's no type relationship that enforces that both be of the same subtype of Real
.
Prefer f(x::Real)
. Extra unnecessary type parameters make things harder for the compiler and slower for dynamic dispatch, not to mention harder to read for other humans.
See the style guide:
Don’t use unnecessary static parameters
A function signature:
foo{T<:Real}(x::T) = ...
should be written as:
foo(x::Real) = ...
instead, especially if T is not used in the function body. Even if T is used, it can be replaced with typeof(x) if convenient. There is no performance difference. Note that this is not a general caution against static parameters, just against uses where they are not needed.
Note also that container types, specifically may need type parameters in function calls. See the FAQ Avoid fields with abstract containers for more information.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With