In Julia I can define a function that accepts all subtypes of Type by doing
function foo{T<:Type}(bar::T, arg::T) end
But this imposes that bar and arg be the same subtype of Type. Is there a shorthand to define a function that accepts different subtypes of Type for bar and arg? I know I can do
function foo{T<:Type, S<:Type}(bar::T, arg::S) end
But for a function with several parameters, it becomes quite cumbersome.
When the type used on the left hand side of T<:Type is an abstract type, then the function argument(s) that are declared to be of type T will accept all things that belong to that abstraction, including things that belong to a subordinate (inheriting) abstraction.
For most purposes, these things are realizations of a concrete type, instantiations of the type. A concrete types may have an abstract type as its supertype, and that abstract type may have a another, more abstract type as its supertype, and so on. Any is the most super supertype, root of the abstract type tree.
In the example
function foo{T<:Type}(bar::T, arg::T) ... end
At each invocation of foo, T takes on exactly one of the subtypes of Type or remains Type itself. That is why bar and arg must share the same specific type for this version of foo to be matched and called. And it explains why the next example matches and is called
function foo{T<:Type, U<:Type}(bar::T, arg::U) ... end
when foo and bar are each subtypes of Type but are realizations of two distinct concrete types (e.g. Int32 and Int64 share the abstract supertype Integer).
There is no general shorthand for using parameters that you intend to accept different sorts of things; that the different sorts share a common abstract type is useful information and allows you to define both the first and the second ways to call foo. That flexible way of managing algorithmic specification often simplifies implementation. That is some of the strength that Julia's multidispatch offers.
There are situations where the use of typealias may simplify writing a function signature. typealias works well to selectively dispatch using nonoverlapping collections of subtypes that share a supertype.
typealias FastInt Union{ Int32, Int64 } # division is fast
typealias SlowInt Union{ Int8, Int128 } # slightly slower
foo{T<:Integer}(a::T, b::T) ... end; # default/fallback
foo{T<:FastInt}(a::T, b::T) ... end; # specialized for fast types
foo{T<:SlowInt}(a::T, b::T) ... end; # specialized for slow types
```
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