# Confusion of :: and \<:

**URL:** <https://discourse.julialang.org/t/confusion-of-and/19221>\
**Category:** New to Julia\
**Created:** [January 3, 2019, 4:13am UTC](https://discourse.julialang.org/t/confusion-of-and/19221 "2019-01-03T04:13:06Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![tomtom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomtom/32/5106_2.png) [@tomtom](https://discourse.julialang.org/u/tomtom)\
**Post date:** [January 3, 2019, 4:13am UTC](https://discourse.julialang.org/t/confusion-of-and/19221/1 "2019-01-03T04:13:06Z")

</div>

happy new year!

I have some confusion around the meaning of `::` and `<:`. Please take a look at the following:

```julia
function f(x::Real)
    println("f ", x)
end

function g1(x::Vector{Real})
    println("g1 ", x)
end

function g2(x::Vector{<:Real})
    println("g2 ", x)
end

julia> f(3)
f 3
julia> f(3.2)
f 3.2

julia> g1([3,2])
ERROR: MethodError: no method matching g1(::Array{Int64,1})
julia> g1([3.0,2.0])
ERROR: MethodError: no method matching g1(::Array{Float64,1})

julia> g2([3,2])
g2 [3, 2]
julia> g2([3.0,2.0])
g2 [3.0, 2.0]

```

We use `::` in `f()` to specify x is a **_subtype_** of `Real` ( **NOT** the **_type_** of `Real`).  
While in `g2()`, we need to use `<:` (rather than `::` ) to specify that the parameter (of the parametric type) is a **_subtype_** of `Real`.  
Note that calling `g1()` always fails.

I have confusion about these notations.

Is it better to fix the meaning of `::` to be “the type of”, and `<:` to be “the subtype of” ? If it’s the case, the following should be allowed (but not now):

```julia
julia> function f2(x<:Real)
           println("f ", x)
       end
ERROR: syntax: "x <: Real" is not a valid function argument name

```

---

<div class="post-metadata">

**Author:** ![yha](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yha/32/3502_2.png) [@yha](https://discourse.julialang.org/u/yha)\
**Post date:** [January 3, 2019, 4:30am UTC](https://discourse.julialang.org/t/confusion-of-and/19221/2 "2019-01-03T04:30:31Z")

</div>

I think the confusion is between instances and subtypes.

> [@tomtom](#):
>
> We use `::` in `f()` to specify x is a _ **subtype** _ of `Real`

`x::Real` in the signature specifies that `x` is an _instance_ of `Real`, not a subtype. `1` is an _instance_ of `Real` (because its type, `Int`, is a _subtype_ of `Real`), so `f(1)` dispatches to this method.

```julia
julia> 1 isa Real
true
julia> 1 <: Real
ERROR: TypeError: in <:, expected Type, got Int64
Stacktrace:
 [1] top-level scope at none:0
julia> typeof(1) <: Real
true

```

`f(Int)` will not dispatch to `f` because `Int` is not an instance of `Real` (`!(Int isa Real)`), although it’s a subtype (`Int <: Real`).  
Similarly, `[3,2] isa Vector{Int} <: Vector{<:Real}` therefore `[3,2] isa Vector{<:Real}`, but `!([3,2] isa Vector{Real})`.  
A syntax like `function f2(x<:Real)` that you suggest seems to imply that this function expects a _type_ as its argument rather than a `Real` value.

---

<div class="post-metadata">

**Author:** ![tomtom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomtom/32/5106_2.png) [@tomtom](https://discourse.julialang.org/u/tomtom)\
**Post date:** [January 3, 2019, 4:37am UTC](https://discourse.julialang.org/t/confusion-of-and/19221/3 "2019-01-03T04:37:14Z")

</div>

a syntax that distinguishes `function f1(x::solidtype)` and `function f2(x<:abstracttype)` is desirable since `f1()` reads “x is an instance of type solidtype”, and `f2()` reads “x is an instance of a soild subtype of abstracttype”. Do you agree?

---

<div class="post-metadata">

**Author:** ![yha](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yha/32/3502_2.png) [@yha](https://discourse.julialang.org/u/yha)\
**Post date:** [January 3, 2019, 4:43am UTC](https://discourse.julialang.org/t/confusion-of-and/19221/4 "2019-01-03T04:43:01Z")

</div>

No, your `f2` reads “`x` is a _subtype_ of `abstracttype`”.  
By “solid subtype” do you mean “concrete subtype”? If so, your proposed reading of `x<:abstracttype` in the signature means exactly the same thing as `x::abstracttype`, since the instances of concrete subtypes of `abstracttype` are precisely the instances of `abstracttype` (if `x isa concretetype <: abstracttype` then it’s also an instance of `abstracttype`. Conversely, if `x isa abstracttype`, it’s also an instance of a concrete subtype of `abstracttype` since every object is an instance of some concrete type).

Do you propose that `::` should be written as `<:` if the type is abstract?

---

<div class="post-metadata">

**Author:** ![tomtom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomtom/32/5106_2.png) [@tomtom](https://discourse.julialang.org/u/tomtom)\
**Post date:** [January 3, 2019, 5:17am UTC](https://discourse.julialang.org/t/confusion-of-and/19221/5 "2019-01-03T05:17:37Z")

</div>

> [@yha](#):
>
> Do you propose that `::` should be written as `<:` if the type is abstract?

exactly

---

<div class="post-metadata">

**Author:** ![bernhard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bernhard/32/2619_2.png) [@bernhard](https://discourse.julialang.org/u/bernhard)\
**Post date:** [January 3, 2019, 6:45am UTC](https://discourse.julialang.org/t/confusion-of-and/19221/6 "2019-01-03T06:45:52Z")

</div>

> [@tomtom](#):
>
> function g2(x::Vector{\<:Real}) println("g2 ", x) end

I see your point (in the first post).  
But I think the second definition of g2 might be written in an abbreviated form (although I am not sure how the full form would look like, maybe …Vector{T}) where T::Real ?). Maybe the non-abbreciated definition is more consistent.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 3, 2019, 7:11am UTC](https://discourse.julialang.org/t/confusion-of-and/19221/7 "2019-01-03T07:11:52Z")

</div>

> [@tomtom](#):
>
> > Do you propose that `::` should be written as `<:` if the type is abstract?
> 
> exactly

As @bernhard is explaining, `::` describes a relationship between a _value_ and a _type_: `x::T` asserts that `x` is of type `T`.

On the other hand, `<:` is an operator which works on relationships between _two types_: If `S <: T` is `true` then `S` is a _subtype_ of `T`. If you change the meaning so that `x <: T` works, that completely changes the meaning of `<:`.

What do you then propose as a new operator to describe subtype relationships?

---

<div class="post-metadata">

**Author:** ![Nosferican](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nosferican/32/9275_2.png) [@Nosferican](https://discourse.julialang.org/u/Nosferican)\
**Post date:** [January 3, 2019, 9:35am UTC](https://discourse.julialang.org/t/confusion-of-and/19221/8 "2019-01-03T09:35:44Z")

</div>

Use `magic(obj::T)` for specifying a method that takes the arguments `typeof(obj) <: T`.  
Now for parametric types such as containers,

```julia
magic(obj::AbstractVector{<:Real})

```

means it will define methods for all arguments of `typeof(obj) <: AbstractVector{<:Real}` such as `1:3` which is a `UnitRange{Int64}`, `zeros(3)` which is a `Vector{Float64}`, etc.

In summary, use `::` when you are defining the type and `<:` when specifying the field type of a parametric type.

I am not sure why the `magic(obj::AbstractVector{Real})` without the `<:` parsers without a syntax error…

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 3, 2019, 9:55am UTC](https://discourse.julialang.org/t/confusion-of-and/19221/9 "2019-01-03T09:55:09Z")

</div>

> [@Nosferican](#):
>
> I am not sure why the `magic(obj::AbstractVector{Real})` without the `<:` parsers without a syntax error…

Maybe I misread you, but why should it be a syntax error?

```julia
julia> obj = Real[2, 3.2]
2-element Array{Real,1}:
 2  
 3.2

julia> obj isa AbstractVector{Real}
true

```

A more elaborate example:

```julia
julia> magic(obj::AbstractVector{Real}) = println("Hello, ", typeof(obj))
magic (generic function with 1 method)

julia> magic(obj::AbstractVector{<:Real}) = println("Bye, ", typeof(obj))
magic (generic function with 2 methods)

julia> magic(Real[2, 3.2])
Hello, Array{Real,1}

julia> magic([2, 3.2])
Bye, Array{Float64,1}

```

---

<div class="post-metadata">

**Author:** ![Nosferican](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nosferican/32/9275_2.png) [@Nosferican](https://discourse.julialang.org/u/Nosferican)\
**Post date:** [January 3, 2019, 1:37pm UTC](https://discourse.julialang.org/t/confusion-of-and/19221/10 "2019-01-03T13:37:31Z")

</div>

Aye, I thought that was deprecated in favor of `where` syntax, but I see it was kept.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 3, 2019, 1:50pm UTC](https://discourse.julialang.org/t/confusion-of-and/19221/11 "2019-01-03T13:50:35Z")

</div>

It’s the other way around, unless I misunderstand you: `AbstractVector{<:Real}` is equivalent to the `where` syntax, while `AbstractVector{Real}` is not.

---

<div class="post-metadata">

**Author:** ![Nosferican](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nosferican/32/9275_2.png) [@Nosferican](https://discourse.julialang.org/u/Nosferican)\
**Post date:** [January 3, 2019, 2:00pm UTC](https://discourse.julialang.org/t/confusion-of-and/19221/12 "2019-01-03T14:00:34Z")

</div>

I usually use type dispatch as,

```julia
magic(obj::AbstractVector{<:Real}) = 0
magic(obj::AbstractVector{<:AbstractFloat}) = 1
magic(obj::AbstractVector{T}) where T<:Float64 = 2

```

instead I think I will switch to,

```julia
magic(obj::AbstractVector{Float64}) = 2

```

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [January 3, 2019, 2:37pm UTC](https://discourse.julialang.org/t/confusion-of-and/19221/13 "2019-01-03T14:37:25Z")

</div>

They are not quite equivalent but probably not in a way that you intended:

```julia
julia> magic(Vector{Union{}}())
2

```

Of course that’s not a very useful vector type since it can’t have any elements.

---

<div class="post-metadata">

**Author:** ![jballanc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jballanc/32/328_2.png) [@jballanc](https://discourse.julialang.org/u/jballanc)\
**Post date:** [January 5, 2019, 12:09am UTC](https://discourse.julialang.org/t/confusion-of-and/19221/14 "2019-01-05T00:09:43Z")

</div>

Unless I’m missing something, I think the original question in this thread doesn’t really have anything to do with `::` and `<:`, but rather with Julia’s invariant subtyping.

In other words, @tomtom was defining a different method than he thought. This:

```julia
function g1(x::Vector{Real})
    println("g1 ", x)
end

```

_does_ in fact define a method that accepts arguments of `Vector{Real}` type or any valid subtype. **However** , if you substitute a subtype (`Int64`) of the parameter (`Real`) for a parameterized type (`Vector{Real}`), you do **not** get a subtype of the parameterized type. So:

```julia
julia> Vector <: AbstractArray
true

julia> Int64 <: Real
true

julia> Vector{Int64} <: Vector{Real}
false

```

which is a departure from many other languages (such as Java and C++).

You can prove this is what’s occurring by forcing the vector type:

```julia
julia> g1([1, 2])
ERROR: MethodError: no method matching g1(::Array{Int64,1})
Closest candidates are:
  g1(::Array{Real,1}) at REPL[1]:1
Stacktrace:
 [1] top-level scope at none:0

julia> g1(Real[1, 2])
g1 Real[1, 2]

```

Note, though, that subtypes of the “outside” type of a parameterized type do count as subtypes (so long as the parameter is of the same type). So:

```julia
function g1_1(x::AbstractArray{Int64})
    println("g1_1 ", x)
end

julia> g1_1([1, 2])
g1_1 [1, 2]

julia> typeof([1, 2])
Array{Int64,1}

```

---

<div class="post-metadata">

**Author:** ![yha](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yha/32/3502_2.png) [@yha](https://discourse.julialang.org/u/yha)\
**Post date:** [January 5, 2019, 6:57am UTC](https://discourse.julialang.org/t/confusion-of-and/19221/15 "2019-01-05T06:57:04Z")

</div>

> [@jballanc](#):
>
> which is a departure from many other languages (such as Java and C++)

Is it? Last time I used those languages (which was a while ago), their generics/templates were invariant, like Julia, though Java has covariant arrays. In C++ you can mimic covariance by defining appropriate conversions/copy constructors, but it’s not the default.
