# Need for explicitly defining subtypes in function arguments?

**URL:** <https://discourse.julialang.org/t/need-for-explicitly-defining-subtypes-in-function-arguments/104883>\
**Category:** New to Julia\
**Created:** [October 12, 2023, 3:20am UTC](https://discourse.julialang.org/t/need-for-explicitly-defining-subtypes-in-function-arguments/104883 "2023-10-12T03:20:43Z")\
**Posts on this page:** 11\
**Page:** 2

<div class="post-metadata">

**Author:** ![hatmatrix](https://avatars.discourse-cdn.com/v4/letter/h/5f8ce5/32.png) [@hatmatrix](https://discourse.julialang.org/u/hatmatrix)\
**Post date:** [October 13, 2023, 1:15pm UTC](https://discourse.julialang.org/t/need-for-explicitly-defining-subtypes-in-function-arguments/104883/22 "2023-10-13T13:15:52Z")

</div>

> Regarding this part of the question specifically, note that Julia specializes code for the given argument types when compiling the function.

Indeed if this is the case then it seems to extend the generalization of subtypes to collections of subtypes would seem intuitive, and apparently possible in other languages - but I see now there is a different philosophy/justification for type invariance.

---

<div class="post-metadata">

**Author:** ![\_bernhard](https://avatars.discourse-cdn.com/v4/letter/_/bc79bd/32.png) [@\_bernhard](https://discourse.julialang.org/u/_bernhard)\
**Post date:** [October 13, 2023, 1:52pm UTC](https://discourse.julialang.org/t/need-for-explicitly-defining-subtypes-in-function-arguments/104883/23 "2023-10-13T13:52:46Z")

</div>

But it is very much possible in julia too, by typing e.g. `Vector{<:Real}`  
It’s just, that the default is invariant und you have to request other behaviours explicitly.

---

<div class="post-metadata">

**Author:** ![hatmatrix](https://avatars.discourse-cdn.com/v4/letter/h/5f8ce5/32.png) [@hatmatrix](https://discourse.julialang.org/u/hatmatrix)\
**Post date:** [October 13, 2023, 2:12pm UTC](https://discourse.julialang.org/t/need-for-explicitly-defining-subtypes-in-function-arguments/104883/25 "2023-10-13T14:12:02Z")

</div>

I suppose it is that simple in the end - just not obvious at first.

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [October 13, 2023, 2:46pm UTC](https://discourse.julialang.org/t/need-for-explicitly-defining-subtypes-in-function-arguments/104883/26 "2023-10-13T14:46:43Z")

</div>

> [@hatmatrix](#):
>
> if I define a function with argument type `Vector{Real}`, I would expect it to take a collection that contains a value `2.5`, which is not an `Int` but `Float`, which is still a subtype of `Real`

If you declare an argument type to be `Vector{Real}`, you are asserting that the argument must be a vector that can hold `Float64` _and_ `Int64` _and_ `Rational` _and_ any other subtype of `Real`. Here’s an example of a function that actually requires the argument to be of type `Vector{Real}` in order to work properly:

```julia
function foo(v::Vector{Real})
    for x in v
        if x isa Int
            println("Found an Int.")
        elseif x isa Float64
            println("Found a Float64.")
        else
            println("Found a different subtype of Real.")
        end
    end
end

```

```julia
julia> x = Real[1, 2.3, 3//4]
3-element Vector{Real}:
  1
  2.3
 3//4

julia> foo(x)
Found an Int.
Found a Float64.
Found a different subtype of Real.

```

---

<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:** [October 13, 2023, 3:51pm UTC](https://discourse.julialang.org/t/need-for-explicitly-defining-subtypes-in-function-arguments/104883/27 "2023-10-13T15:51:28Z")

</div>

> [@hatmatrix](#):
>
> if I define a function with argument type `Vector{Real}`, I would expect it to take a collection that contains a value `2.5`, which is not an `Int` but `Float`, which is still a subtype of `Real`. I would not expect that for a function with argument type `Vector{Int}`.

I’m taking about what a `Vector{Real}` _is_:

- A `Vector{Real}` must be able to hold a float value.
- A `Vector{Int}` cannot hold a float value.
- Ergo, a `Vector{Int}` is not a `Vector{Real}`.
- Equivalently, a `Vector{Int}` is not a subtype of `Vector{Real}`.

Additionally, a `Vector{Real}` is a concrete type. Concrete types cannot have subtypes.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [October 13, 2023, 4:17pm UTC](https://discourse.julialang.org/t/need-for-explicitly-defining-subtypes-in-function-arguments/104883/28 "2023-10-13T16:17:25Z")

</div>

The difference is not in the initial content of the vector, but in what can be put into it by the function. Suppose the function accepts `Vector{Real}`, does `push!(v, 2.5)` and you passed `Vector{Int}` – the function will fail unexpectedly. That’s why it is prohibited.

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [October 13, 2023, 4:41pm UTC](https://discourse.julialang.org/t/need-for-explicitly-defining-subtypes-in-function-arguments/104883/29 "2023-10-13T16:41:13Z")

</div>

Note, yyou don’t _need_ to define subtypes (or any types) in _function_ definitions (but you want to for `struct`s, for speed), e.g. not:

```julia
g(x::Array{Real}) = x .* 2

```

You can just do e.g.:

```julia
g(x) = x .* 2

```

and it’s NEVER slower, nor “wrong”. But it allows more than you might think, and that’s ok (and for something that doesn’t make sense, means a runtime error):

```julia
julia> pow2(x) = x ^ 2

julia> pow2("Palli")
"PalliPalli"

```

If you want to be specific you want some type of array, document that way for your users, then it’s neither wrong, but then you may want to be as general as possible, i.e. not just allow Aarry, but any subtype of AbstractArray, and likely containing any type (or maybe of just some).

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [October 13, 2023, 4:49pm UTC](https://discourse.julialang.org/t/need-for-explicitly-defining-subtypes-in-function-arguments/104883/30 "2023-10-13T16:49:33Z")

</div>

> [@hatmatrix](#):
>
> but I see now there is a different philosophy/justification for type invariance.

Since noone seems to have linked it so far, there’s also this explanation by @StefanKarpinski (though with a slight Rust bend, as that was the original question there):

> [@Reason behind designing parametric types as invariant](https://discourse.julialang.org/t/reason-behind-designing-parametric-types-as-invariant/18971/2):
>
> In a sense we do: If we look at our table of variances, we see that &mut T is invariant over T . As it turns out, this completely fixes the issue! Since all types in Julia behave like &mut T in Rust (or at least there’s no way of expressing anything else in the type system—there are immutable types and reference types but they are all treated uniformly), that fact translated to Julia would imply that all parametric types are invariant, which is precisely what we do. In order to do somet…

---

<div class="post-metadata">

**Author:** ![hatmatrix](https://avatars.discourse-cdn.com/v4/letter/h/5f8ce5/32.png) [@hatmatrix](https://discourse.julialang.org/u/hatmatrix)\
**Post date:** [October 14, 2023, 8:43pm UTC](https://discourse.julialang.org/t/need-for-explicitly-defining-subtypes-in-function-arguments/104883/31 "2023-10-14T20:43:29Z")

</div>

Thanks - this does answer my original question - why you want that the subtypes not be allowed on some cases.

---

<div class="post-metadata">

**Author:** ![hatmatrix](https://avatars.discourse-cdn.com/v4/letter/h/5f8ce5/32.png) [@hatmatrix](https://discourse.julialang.org/u/hatmatrix)\
**Post date:** [October 14, 2023, 8:44pm UTC](https://discourse.julialang.org/t/need-for-explicitly-defining-subtypes-in-function-arguments/104883/32 "2023-10-14T20:44:26Z")

</div>

Super informative thread. I shared the same assumptions as the original poster.

---

<div class="post-metadata">

**Author:** ![hatmatrix](https://avatars.discourse-cdn.com/v4/letter/h/5f8ce5/32.png) [@hatmatrix](https://discourse.julialang.org/u/hatmatrix)\
**Post date:** [October 14, 2023, 8:46pm UTC](https://discourse.julialang.org/t/need-for-explicitly-defining-subtypes-in-function-arguments/104883/33 "2023-10-14T20:46:46Z")

</div>

Indeed the heterogenous array case I also failed to think about, but would be a case where subtypes should not implicitly allowed. Thanks - was informative.

[Previous page](https://discourse.julialang.org/t/need-for-explicitly-defining-subtypes-in-function-arguments/104883.md?page=1)
