# Iterating over Range\<char\>?

**URL:** <https://internals.rust-lang.org/t/iterating-over-range-char/8965>\
**Category:** Uncategorized\
**Created:** [December 5, 2018, 6:05pm UTC](https://internals.rust-lang.org/t/iterating-over-range-char/8965 "2018-12-05T18:05:17Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![birkenfeld](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/birkenfeld/32/1150_2.png) [@birkenfeld](https://internals.rust-lang.org/u/birkenfeld)\
**Post date:** [December 5, 2018, 6:05pm UTC](https://internals.rust-lang.org/t/iterating-over-range-char/8965/1 "2018-12-05T18:05:17Z")

</div>

Today I found myself, for advent-related reasons, wanting to iterate over `'a'..='z'`. Turns out this isn’t possible since `char` doesn’t implement `Step`, and looking at it, a lot of `Step` doesn’t make too much sense for `char`:

- `replace_zero`, `replace_one` (both of which appear unused in the rustc codebase though)
- `add_one` and `sub_one`: they don’t seem to allow for failure and just overflow? (also, how to handle the gap with surrogates?)

It also seems that `Step` isn’t going to last: should I wait with this until that time?

---

<div class="post-metadata">

**Author:** ![leonardo](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/leonardo/32/1344_2.png) [@leonardo](https://internals.rust-lang.org/u/leonardo)\
**Post date:** [December 5, 2018, 6:08pm UTC](https://internals.rust-lang.org/t/iterating-over-range-char/8965/2 "2018-12-05T18:08:40Z")

</div>

In some cases you solve the problem with:

`(b'a' ..= b'z').map(char::from)`

---

<div class="post-metadata">

**Author:** ![birkenfeld](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/birkenfeld/32/1150_2.png) [@birkenfeld](https://internals.rust-lang.org/u/birkenfeld)\
**Post date:** [December 5, 2018, 6:10pm UTC](https://internals.rust-lang.org/t/iterating-over-range-char/8965/3 "2018-12-05T18:10:19Z")

</div>

That’s what I did, essentially. It feels like I should be able to do this with `char`s directly, though.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [December 5, 2018, 6:43pm UTC](https://internals.rust-lang.org/t/iterating-over-range-char/8965/4 "2018-12-05T18:43:41Z")

</div>

I made [`unic-char-range`](https://crates.io/crates/unic-char-range) a while back for this (in the context of the unic group of libraries), which iirc offers both a custom Iterator as well as a `from_u32` map for when either case optimize better.

I'd be happy to see `Range<char>` "just work", though. (2023 update, since I got a "popular link" notification for this post: `Range<char>` does just work now! (Hopefully I didn't necrobump the thread...) And I did the impl work for that to be the case 😊)

(I'd also be willing to make a standalone char-range and make the unic one just re-export it, since unic is on an indefinite hiatus)

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [December 5, 2018, 6:45pm UTC](https://internals.rust-lang.org/t/iterating-over-range-char/8965/5 "2018-12-05T18:45:16Z")

</div>

I think iterating over a range of chars should be possible, and chars should just skip the gap if a range would iterate past it. chars have a defined order and a defined set of valid values, so iterating through a set of consecutive values should be possible (and it shouldn’t fail).

replace\_zero and replace\_one seem like very odd methods, it doesnt seem correct to assume anything that can be “stepped” has a conceptual one and zero.

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)\
**Post date:** [December 5, 2018, 7:08pm UTC](https://internals.rust-lang.org/t/iterating-over-range-char/8965/6 "2018-12-05T19:08:31Z")

</div>

Rust `char` permits any [Unicode scalar value](http://www.unicode.org/glossary/#unicode_scalar_value), “0 to D7FF16 and E00016 to 10FFFF16 inclusive.” But the vast majority of these values are unassigned, which makes ranges less useful IMO.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [December 5, 2018, 7:57pm UTC](https://internals.rust-lang.org/t/iterating-over-range-char/8965/7 "2018-12-05T19:57:14Z")

</div>

The main use unic gets out of character ranges is doing a “for all codepoints” test, which is useful for text processing libraries to catch low-hanging fruit errors.

For the general crowd, though, I agree; what is actually useful (if anything) is iteration over the set of codepoints with a specific General\_Category or other binary property. (That is, the of codepoints matched my a `\p{something}` regex.)

---

<div class="post-metadata">

**Author:** ![burntsushi](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/burntsushi/32/279_2.png) [@burntsushi](https://internals.rust-lang.org/u/burntsushi)\
**Post date:** [December 5, 2018, 10:09pm UTC](https://internals.rust-lang.org/t/iterating-over-range-char/8965/8 "2018-12-05T22:09:56Z")

</div>

regex also uses it: [https://github.com/rust-lang/regex/blob/d4b9419ed41907d5e8b43166ce7aef77e6fb93d9/regex-syntax/src/hir/mod.rs#L866](https://github.com/rust-lang/regex/blob/d4b9419ed41907d5e8b43166ce7aef77e6fb93d9/regex-syntax/src/hir/mod.rs#L866)

I have wanted it more than once in tests.

In general though, I don’t need this particular type of iteration very often. I did similarly want it in today’s AoC puzzle, and I did actually write `'A'..='Z'` first!

---

<div class="post-metadata">

**Author:** ![flundstrom2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/flundstrom2/32/2392_2.png) [@flundstrom2](https://internals.rust-lang.org/u/flundstrom2)\
**Post date:** [December 7, 2018, 2:30pm UTC](https://internals.rust-lang.org/t/iterating-over-range-char/8965/9 "2018-12-07T14:30:29Z")

</div>

> > > @birkenfeld: Today I found myself, for advent-related reasons, wanting to iterate over `'a'..='z'` . Turns out this isn’t possible since `char` doesn’t implement `Step`
> > 
> > @CAD97: I’d be happy to see `Range<char>` “just work”, though.
> 
> @withoutboats: I think iterating over a range of chars should be possible, and chars should just skip the gap if a range would iterate past it. chars have a defined order and a defined set of valid values, so iterating through a set of consecutive values should be possible (and it shouldn’t fail).

Iterating over chars, in terms of letters, are completely different from iterating over chars in terms of unicode code-points. Say, you want to iterate over `'a'..='z'`, how many chars will that be?

The naïve response is 26, but that is if you iterate over the English alphabet. However, if the program is written on an English computer, but run on a non-English computer, the result would be different: For example, the Icelandic alphabet doesn't even contain **z** anymore, so it would imply an undefined behaviour. And even if the alphabet did contain **z** (which it actually have had) , the Icelandic alphabet contains 32 letters: `'a'..='ö'`

The letter **ö** , by the way, has code-point U+00F6, quite far from **z**. Not to mention the fact that the letters between **a** and **d** , are **á** (code-point U+00E1), and **b** , but no **c**. Another interesting thing, is that prior to 2006, **w** was not a letter in itself in the Swedish alphabet. Instead it was sorted together with **v**.

All those examples are trivial - it gets even worse when we leave the unicode Latin-1 block and get code-points above U+00FF ...

So, for a properly working char iterator - treating chars as letters, rather than code-points - it must take the locale into account, and also handle the issues when the user's computer doesn't even contain the letters representing the start and end of the set.

So, all in all, a char iterator is really more tied to the concept of locales, rather than unicode.

---

<div class="post-metadata">

**Author:** ![burntsushi](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/burntsushi/32/279_2.png) [@burntsushi](https://internals.rust-lang.org/u/burntsushi)\
**Post date:** [December 7, 2018, 2:45pm UTC](https://internals.rust-lang.org/t/iterating-over-range-char/8965/10 "2018-12-07T14:45:20Z")

</div>

A `char` is defined as a Unicode scalar value and the set of all Unicode scalar values defines an ordering without regard to locale. That ordering is, in and of itself, useful. Locale specific orderings are also useful in their own context. Rust’s standard library does not do any locale specific tailoring that is described in Unicode, and instead leaves that to ecosystem crates. I would think the same principle should apply here.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:31am UTC](https://internals.rust-lang.org/t/iterating-over-range-char/8965/11 "2019-03-25T08:31:16Z")

</div>

Closed on March 25, 2019, 8:31am UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
