# Why is AbstractString not a subtype of AbstractVector?

**URL:** <https://discourse.julialang.org/t/why-is-abstractstring-not-a-subtype-of-abstractvector/69189>\
**Category:** General Usage\
**Tags:** strings\
**Created:** [October 4, 2021, 12:14pm UTC](https://discourse.julialang.org/t/why-is-abstractstring-not-a-subtype-of-abstractvector/69189 "2021-10-04T12:14:18Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![jonas-schulze](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jonas-schulze/32/9228_2.png) [@jonas-schulze](https://discourse.julialang.org/u/jonas-schulze)\
**Post date:** [October 4, 2021, 12:14pm UTC](https://discourse.julialang.org/t/why-is-abstractstring-not-a-subtype-of-abstractvector/69189/1 "2021-10-04T12:14:18Z")

</div>

While working on [https://github.com/JuliaCollections/DataStructures.jl/pull/759](https://github.com/JuliaCollections/DataStructures.jl/pull/759), which I thought would be a funny solution to a project euler riddle, I noticed that `String` is not a subtype of `AbstractVector{Char}`. Are there good reasons against making `AbstractString <: AbstractVector`? Or even `<: AbstractVector{AbstractChar}`?

---

<div class="post-metadata">

**Author:** ![SteffenPL](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/steffenpl/32/206270_2.png) [@SteffenPL](https://discourse.julialang.org/u/SteffenPL)\
**Post date:** [October 4, 2021, 12:31pm UTC](https://discourse.julialang.org/t/why-is-abstractstring-not-a-subtype-of-abstractvector/69189/2 "2021-10-04T12:31:55Z")

</div>

Not an answer, but this seems related to your last question: [Vector{Int} \<: Vector{Real} is false??? · JuliaNotes.jl](https://m3g.github.io/JuliaNotes.jl/stable/typevariance/)

The `<:` behaves sometimes a little bit different with regard to the element types…

---

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [October 4, 2021, 12:47pm UTC](https://discourse.julialang.org/t/why-is-abstractstring-not-a-subtype-of-abstractvector/69189/3 "2021-10-04T12:47:03Z")

</div>

There are various reasons for considering strings something totally different from vectors of chars. For me, an important one is vectors are mutable objects, whereas strings are not. Also, indexing the characters of a string in the fashion of indexing vectors (i.e. `x[i]` with `i` being an integer) gives wrong results in strings with Unicode characters.

---

<div class="post-metadata">

**Author:** ![MarcMush](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcmush/32/18006_2.png) [@MarcMush](https://discourse.julialang.org/u/MarcMush)\
**Post date:** [October 4, 2021, 1:28pm UTC](https://discourse.julialang.org/t/why-is-abstractstring-not-a-subtype-of-abstractvector/69189/4 "2021-10-04T13:28:27Z")

</div>

another big problem with `String`s compared to `Vector`s is that not all indices in the range `begin:end` are valid:

```julia-repl
julia> a="∈b"
"∈b"

julia> a[2]
ERROR: StringIndexError: invalid index [2], valid nearby indices [1]=>'∈', [4]=>'b'
Stacktrace:
 [1] string_index_err(s::String, i::Int64)
   @ Base ./strings/string.jl:12
 [2] getindex_continued(s::String, i::Int64, u::UInt32)
   @ Base ./strings/string.jl:233
 [3] getindex(s::String, i::Int64)
   @ Base ./strings/string.jl:226
 [4] top-level scope
   @ REPL[5]:1

```

(`nextind(a,1)` should be used instead)

---

<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 4, 2021, 1:32pm UTC](https://discourse.julialang.org/t/why-is-abstractstring-not-a-subtype-of-abstractvector/69189/5 "2021-10-04T13:32:58Z")

</div>

Another difference: `String`s are treated as scalars by broadcasting:

```julia
jl> println.("Hello, ", 1:7);
Hello, 1
Hello, 2
Hello, 3
Hello, 4
Hello, 5
Hello, 6
Hello, 7

```

vs

```julia
jl> println.(['H', 'e', 'l', 'l', 'o', ',', ' '], 1:7);
H1
e2
l3
l4
o5
,6
 7

```

---

<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:** [October 4, 2021, 2:52pm UTC](https://discourse.julialang.org/t/why-is-abstractstring-not-a-subtype-of-abstractvector/69189/6 "2021-10-04T14:52:43Z")

</div>

> [@heliosdrm](#):
>
> vectors are mutable objects

Not necessarily: ranges like `1:10` are ~~mutable~~ immutable `AbstractVectors`, as are `SVectors` from StaticArrays.jl and many other examples.

I think the main technical reason that `AbstractString` is not a subtype of `AbstractVector` is that the indices of a `String` are not necessarily consecutive, and in consequence there is no O(1) algorithm to “give me the n-th character of a string” (`str[nextind(str, 0, n)]` in Julia).

Conceptually, however, one rarely views a `String` as a collection of characters, in part because the concept of a “character” is itself ambiguous in Unicode. For example, `"no\u00EBl"== "noël"` and `"noe\u0308l" == "noël"` are [canonically equivalent](https://en.wikipedia.org/wiki/Unicode_equivalence) strings in Unicode, but the former has `length` 5 and the latter has `length` 4 (i.e., different numbers of [codepoints](https://en.wikipedia.org/wiki/Code_point), depending on whether a [combining character](https://en.wikipedia.org/wiki/Combining_character) is used to make the `ë`). For a similar reason, it’s not generally _useful_ to ask for the “n-th character of a string” where `n` is chosen at random.

(It _is_ useful to be able to read from an index that was located previously, e.g. by a `find` function, but in that case the index is just an arbitrary position indicator in the string and you don’t care how many characters it corresponds to.)

(Conversely, `codeunits(str)` for a string `str` _does_ give a subtype of `AbstractVector`, but the elements of this array are not characters, but rather the elementary units of the unicode encoding of the string—bytes, for `String` with its UTF-8 encoding.)

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [October 4, 2021, 3:23pm UTC](https://discourse.julialang.org/t/why-is-abstractstring-not-a-subtype-of-abstractvector/69189/7 "2021-10-04T15:23:56Z")

</div>

> [@stevengj](#):
>
> Not necessarily: ranges are mutable `AbstractVectors` , as are `SVectors` from StaticArrays.jl and many other examples.

Nit: immutable

---

<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:** [October 4, 2021, 3:35pm UTC](https://discourse.julialang.org/t/why-is-abstractstring-not-a-subtype-of-abstractvector/69189/8 "2021-10-04T15:35:24Z")

</div>

> [@kristoffer.carlsson](#):
>
> Nit: immutable

Thanks, fixed.

---

<div class="post-metadata">

**Author:** ![Dennis16](https://avatars.discourse-cdn.com/v4/letter/d/8e8cbc/32.png) [@Dennis16](https://discourse.julialang.org/u/Dennis16)\
**Post date:** [October 6, 2021, 5:31am UTC](https://discourse.julialang.org/t/why-is-abstractstring-not-a-subtype-of-abstractvector/69189/9 "2021-10-06T05:31:19Z")

</div>

> [@heliosdrm](#):
>
> There are various reasons for considering strings something totally different from vectors of chars. For me, an important one is vectors are mutable objects, whereas strings are not. Also, indexing the characters of a string in the fashion of indexing vectors (i.e. `x[i]` with `i` being an integer) gives wrong results in strings with Unicode characters.

Thanks for update and quick response[,](https://www.walgreenslistens.life/) it’s too helpful.

---

<div class="post-metadata">

**Author:** ![Bardo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bardo/32/21601_2.png) [@Bardo](https://discourse.julialang.org/u/Bardo)\
**Post date:** [October 7, 2021, 11:14am UTC](https://discourse.julialang.org/t/why-is-abstractstring-not-a-subtype-of-abstractvector/69189/10 "2021-10-07T11:14:28Z")

</div>

Just wondered what is the best way to convert between string and vector of characters:

```julia
julia> s = "toto"
"toto"

julia> vc = collect(s)
4-element Vector{Char}:
 't': ASCII/Unicode U+0074 (category Ll: Letter, lowercase)
 'o': ASCII/Unicode U+006F (category Ll: Letter, lowercase)
 't': ASCII/Unicode U+0074 (category Ll: Letter, lowercase)
 'o': ASCII/Unicode U+006F (category Ll: Letter, lowercase)

julia> s = String(vc)
"toto"

```

---

<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:** [October 7, 2021, 1:28pm UTC](https://discourse.julialang.org/t/why-is-abstractstring-not-a-subtype-of-abstractvector/69189/11 "2021-10-07T13:28:28Z")

</div>

Those are good ways to do it. Note that collecting a string into a vector of characters potentially blows up the storage by up to 4x.
