# Proper way to deal with \`Vector{Any}\` when defining a function

**URL:** <https://discourse.julialang.org/t/proper-way-to-deal-with-vector-any-when-defining-a-function/114422>\
**Category:** General Usage\
**Tags:** question, type, function\
**Created:** [May 18, 2024, 9:00am UTC](https://discourse.julialang.org/t/proper-way-to-deal-with-vector-any-when-defining-a-function/114422 "2024-05-18T09:00:50Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [May 18, 2024, 9:00am UTC](https://discourse.julialang.org/t/proper-way-to-deal-with-vector-any-when-defining-a-function/114422/1 "2024-05-18T09:00:50Z")

</div>

```julia
function catstr(arr::Vector{String})
    return reduce(*, arr)
end

# Method-1: OK
arr = ["hello", "world"]
catstr(arr)

# Method-2: Not OK
arr = []
push!(arr, "hello")
push!(arr, "world")
catstr(arr)

```

Whose fault? Is the function not defined well enough, or is it called improperly?

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [May 18, 2024, 10:36am UTC](https://discourse.julialang.org/t/proper-way-to-deal-with-vector-any-when-defining-a-function/114422/2 "2024-05-18T10:36:48Z")

</div>

> [@WuSiren](#):
>
> Is the function not defined well enough, or is it called improperly?

That’s really up to you. The function is called `catstr` so it’s actually very reasonable to restrict the input to a collection of `String`s like `Vector{String}`. Then it’s a matter of making sure your inputs fit. `Vector{Any}` doesn’t fit because you could put non-strings in there. To make an empty `Vector{String}`, do `arr = String[]`. That change alone makes your code work again.

If you want to expand what `catstr` works on, you could change the argument annotation. Removing it entirely is the same as `::Any`, which allows many inputs that error at the `reduce` call. `::Vector` would allow vectors containing other things, which could let the `reduce` call work but in a way that doesn’t fit the name `catstr`. Off the top of my head, the most liberal annotation fitting the name would be `catstr(arr::AbstractArray{T,N} where N) where T<:AbstractString`.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [May 18, 2024, 12:26pm UTC](https://discourse.julialang.org/t/proper-way-to-deal-with-vector-any-when-defining-a-function/114422/3 "2024-05-18T12:26:29Z")

</div>

> [@WuSiren](#):
>
> ```julia
> arr = []
> push!(arr, "hello")
> push!(arr, "world"
> 
> ```

The above is equivalent to the following.

```julia
arr = Any[]
push!(arr, "hello")
push!(arr, "world"

```

To avoid `Vector{Any}` do

```julia
arr = String[]
push!(arr, "hello")
push!(arr, "world"

```

If you cannot avoid it, the do:

```julia
julia> arr = Any[]
Any[]

julia> push!(arr, "hello")
1-element Vector{Any}:
 "hello"

julia> push!(arr, "world")
2-element Vector{Any}:
 "hello"
 "world"

julia> arr = identity.(arr)
2-element Vector{String}:
 "hello"
 "world"

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [May 18, 2024, 1:04pm UTC](https://discourse.julialang.org/t/proper-way-to-deal-with-vector-any-when-defining-a-function/114422/4 "2024-05-18T13:04:04Z")

</div>

> [@WuSiren](#):
>
> ```julia
> function catstr(arr::Vector{String})
> return reduce(*, arr)
> end
> 
> ```

On a separate note, this is pretty inefficient because every call to `*` allocates a new string, Better to call `join`. To implement this sort of function yourself, write to an `IOBuffer` that you convert to a string at the end.

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [May 18, 2024, 2:08pm UTC](https://discourse.julialang.org/t/proper-way-to-deal-with-vector-any-when-defining-a-function/114422/5 "2024-05-18T14:08:35Z")

</div>

Thank you all! I’ve learned more than what I asked.

---

<div class="post-metadata">

**Author:** ![screw\_dog](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/screw_dog/32/48119_2.png) [@screw\_dog](https://discourse.julialang.org/u/screw_dog)\
**Post date:** [May 18, 2024, 3:14pm UTC](https://discourse.julialang.org/t/proper-way-to-deal-with-vector-any-when-defining-a-function/114422/6 "2024-05-18T15:14:20Z")

</div>

> [@WuSiren](#):
>
> ```julia
> function catstr(arr::Vector{String})
> return reduce(*, arr)
> end
> 
> ```

I’d strongly recommend against restricting your functions to just `String` as `SubString`s are also very common and are being excluded.

For example:

```julia
str = "Test String"
ss = split(str)
catstr(ss) # errors

```

You almost always just want to restrict to subtypes of `AbstractString`

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [May 18, 2024, 4:08pm UTC](https://discourse.julialang.org/t/proper-way-to-deal-with-vector-any-when-defining-a-function/114422/7 "2024-05-18T16:08:35Z")

</div>

May I ask, is there a hierarchical graph of all types in Julia? Or how can I view the type hierarchy graph involved in the current workspace?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [May 18, 2024, 4:32pm UTC](https://discourse.julialang.org/t/proper-way-to-deal-with-vector-any-when-defining-a-function/114422/8 "2024-05-18T16:32:28Z")

</div>

> [@screw\_dog](#):
>
> I’d strongly recommend against restricting your functions to just `String` as `SubString`s are also very common and are being excluded.

In particular, a more general signature would be `function catstr(arr::AbstractVector{<:AbstractString})`. (However, you can always broaden the types later.)

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [May 18, 2024, 11:09pm UTC](https://discourse.julialang.org/t/proper-way-to-deal-with-vector-any-when-defining-a-function/114422/9 "2024-05-18T23:09:56Z")

</div>

> [@WuSiren](#):
>
> May I ask, is there a hierarchical graph of all types in Julia? Or how can I view the type hierarchy graph involved in the current workspace?

The entire hierarchy? Are you sure?

```julia-repl
julia> using AbstractTrees, TerminalPager

julia> AbstractTrees.children(d::Type) = subtypes(d)

julia> @stdout_to_pager print_tree(Any)
Any
├─ AbstractArray
│ ├─ AbstractRange
│ │ ├─ LinRange
│ │ ├─ OrdinalRange
│ │ │ ├─ AbstractUnitRange
│ │ │ │ ├─ IdentityUnitRange
│ │ │ │ ├─ OneTo
│ │ │ │ ├─ Slice
│ │ │ │ └─ UnitRange
│ │ │ └─ StepRange
│ │ └─ StepRangeLen
│ ├─ AbstractSlices
│ │ └─ Slices
│ ├─ ExceptionStack
│ ├─ LogicalIndex
│ ├─ MethodList
│ ├─ ReinterpretArray
│ ├─ ReshapedArray
│ ├─ SCartesianIndices2
│ ├─ WithoutMissingVector
│ ├─ BitArray
│ ├─ CartesianIndices
│ ├─ AbstractRange
│ │ ├─ LinRange
│ │ ├─ OrdinalRange
│ │ │ ├─ AbstractUnitRange
│ │ │ │ ├─ IdentityUnitRange
│ │ │ │ ├─ OneTo
│ │ │ │ ├─ Slice
│ │ │ │ ├─ StmtRange
│ │ │ │ └─ UnitRange
│ │ │ └─ StepRange
│ │ └─ StepRangeLen
│ ├─ BitArray
│ ├─ ExceptionStack

```

Maybe a few smaller selections might help.

```julia-repl
julia> print_tree(AbstractString)
AbstractString
├─ LazyString
├─ LazyString
├─ String
├─ SubString
└─ SubstitutionString

julia> print_tree(Number)
Number
├─ MultiplicativeInverse
├─ Complex
└─ Real
   ├─ AbstractFloat
   │ ├─ BigFloat
   │ ├─ Float16
   │ ├─ Float32
   │ └─ Float64
   ├─ AbstractIrrational
   │ └─ Irrational
   ├─ Integer
   │ ├─ Bool
   │ ├─ Signed
   │ │ ├─ BigInt
   │ │ ├─ Int128
   │ │ ├─ Int16
   │ │ ├─ Int32
   │ │ ├─ Int64
   │ │ └─ Int8
   │ └─ Unsigned
   │ ├─ UInt128
   │ ├─ UInt16
   │ ├─ UInt32
   │ ├─ UInt64
   │ └─ UInt8
   └─ Rational

```

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [May 19, 2024, 1:01am UTC](https://discourse.julialang.org/t/proper-way-to-deal-with-vector-any-when-defining-a-function/114422/10 "2024-05-19T01:01:28Z")

</div>

Thanks! Very helpful! But what does this mean?

> [@mkitti](#):
>
> `julia> AbstractTrees.children(d::Type) = subtypes(d)`

---

<div class="post-metadata">

**Author:** ![Sevi](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Sevi](https://discourse.julialang.org/u/Sevi)\
**Post date:** [May 19, 2024, 7:44am UTC](https://discourse.julialang.org/t/proper-way-to-deal-with-vector-any-when-defining-a-function/114422/11 "2024-05-19T07:44:12Z")

</div>

It’s explained in the documentation of AbstractTrees.jl:  
[https://juliacollections.github.io/AbstractTrees.jl/stable/](https://juliacollections.github.io/AbstractTrees.jl/stable/)

> Using this package involves implementing the abstract tree interface which, at a minimum, requires defining the function [`AbstractTrees.children`](https://juliacollections.github.io/AbstractTrees.jl/stable/#AbstractTrees.children) for an object.

By defining how to get all children from a `Type` object (= simply look up its `subtypes`), we can immediately print the whole type tree “unterneath” (or “above” ? 😅 ) the given type.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [May 19, 2024, 10:13am UTC](https://discourse.julialang.org/t/proper-way-to-deal-with-vector-any-when-defining-a-function/114422/12 "2024-05-19T10:13:43Z")

</div>

> [@WuSiren](#):
>
> Thanks! Very helpful! But what does this mean?
> 
> > [@mkitti](#):
> >
> > `julia> AbstractTrees.children(d::Type) = subtypes(d)`

This is a short hand notation for a function definition.

```julia
using AbstractTrees

function AbstractTrees.children(d::Type)
    return subtypes(d)
end

```

That in turn is also a short hand for the following.

```julia
import AbstractTrees: children

function children(d::Type)
    return subtypes(d)
end

```

We extend the method `children` from `AbstractTrees` for `Type` such that it maps to `InteractiveUtils.subtypes`.

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [May 19, 2024, 10:37am UTC](https://discourse.julialang.org/t/proper-way-to-deal-with-vector-any-when-defining-a-function/114422/13 "2024-05-19T10:37:54Z")

</div>

Oh! I see. Thanks! @mkitti @Sevi
