foo(::T, a::S) where {T,S} - the first argument of foo is a (non-usable) variable of type T, the second, namely a of type S.
foo(::Type{T}, a::S)- the first argument of foo is the type T, the second is of type S.
So, the difference between ::T and ::Type{T} is that they request either a variable of type T or a variable which is the type T itself. In julia types are data as well.
Indeed, this is a very basic question that is easily addressed by reading the documentation and actually running the code in question and seeing its effects.
Please everyone, keep in mind that this question was appropriately posted in the usage / first steps category. Even if something is documented, itβs still not a problem to ask a question about it! Hopefully the answers here help clarify things for @vickysharma0812.
Type{T} is admittedly slightly unintuitive as it provides an unexpected branch in the type tree
DataType <-------- Float64
Type{Float64} <-/
julia> typeof(Float64)
DataType
julia> Float64 isa DataType
true
julia> Float64 isa Type{Float64} # This in comibnation with the next line might be unexpected
true
julia> DataType isa Type{Float64}
false
which the documentation hints at by calling it βspecialβ
Just to add on, often, when you are new to something, even if you read the documentation not everything clicks. More often than not you are unsure why some passage or sentence matters until youβve understood the concepts. This is why itβs helpful to point to the documentation and explain briefly the concepts as well.
@carstenbauer, I guess you know this, but according to print_tree, DataType is a leaf on the βtreeβ. (It is the unique element on the branch of subtypes.)
However, according to isa (mentioned in @baggepinnenβs post), all the following evaluate to true:
isa(Type, Any)
isa(Any, Type)
isa(DataType, Any)
isa(Any, DataType).
But DataType is not really at the top/bottom of the order because, in addition, we have
isa(Type, DataType) is false
isa(DataType, Type) is true.
But also note that this violation of transitivity (DataType <: Type ~: Any ~: DataType) implies that, once we include Singleton Types, we do not have a preorder let alone a partial order or a tree.
I might try and create a graph on the basis of isa to get a lovely diagram like yours as a way of honing my Julia skills. At the moment, I canβt see a completely obvious way on the basis of the existing functions in AbstractTrees.
I think you are confusing things. isa shows if the type of the first argument<: the second argument. So does not make sense to me to use isa to establish any ordering/tree, you should be using <: for it.
julia> Any <: Type
false
julia> Type <: Any
true
julia> Any <: DataType
false
julia> DataType <: Any
true
You should not use isa passing a type as the first argument, because it will always be the same as DataType <: second_isa_argument because the type of any type will be DataType.
julia> Int64 isa Type{Int64}
true
julia> DataType <: Type{Int64}
false
I canβt find it, but there is a recording of a talk, probably given by Jeff, that shows a 2D grid layout of values, with one dimension showing a subtyping relation and another dimension showing the typeof relation. It shows the following self-loops:
julia> typeof(DataType)
DataType
julia> supertype(Any)
Any
If someone can find that talk, I would appreciate a time-link to it and a screenshot of that slide.
we can safely say that Any is both of type Any and of type DataType. The whole point of type hierarchies is to be able to think of βmeta typesβ as being inside the system. Otherwise we are artificially restricting ourselves to reasoning/operating at a lower level.
Letβs also agree that isa and <: can be described as two distinct binary relations, both of which describe relationships among types. You will note that on Types Β· The Julia Language, there are certain more abstract types where isa is used instead of <: . I expect that <: does not account for relationships higher-up the type hierarchy.
I guess the first natural question to ask is whether <: is a partial order.
Also, although my arguments in the previous post show that isa is not a preorder. They do not exclude the possibility that <: is a subrelation of isa, where some symmetry relationships under isa are broken by <: .
You are correct, I forgot this exception. However, Type{T} where {T} is kinda of a special object, it represents the singleton type for which the only instance is T (this is literally the documentation of Core.Type). I believe we cannot have typeof(Int64) as Type{Int64} because then typeof(typeof(Int64)) would be Type{Type{Int64}} and so on, instead of the cycle at DataType but I am not sure what would break by doing this.
If you tried to follow what I meant by my statement then you missed it: