ベスパリブ

プログラミングを主とした日記・備忘録です。ベスパ持ってないです。

Rust の Range は char の範囲指定もできる

環境・バージョン

> rustup show
Default host: x86_64-pc-windows-msvc
rustup home:  C:\Users\****\.rustup

stable-x86_64-pc-windows-msvc (default)
rustc 1.58.1 (db9d1b20b 2022-01-20)

Rust の Range と パターンマッチング

Rustではパターンマッチングで閉区間のRangeが使える。

fn main() {
    let a: i8 = 10;

    match a {
        0..=10 => { println!("yes"); }
        _ => { println!("no"); }
    }
    // yes
}

残念ながら半開区間だとエラーが発生する。詳しくはここの議論を参照。

    match a {
        0..10 => { println!("yes"); }
        _ => { println!("no"); }
    }
error[E0658]: exclusive range pattern syntax is experimental
  --> src\main.rs:37:13
   |
37 |             0..10 => { println!("yes"); }
   |             ^^^^^
   |
   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information

Range は char の範囲指定もできる

ascii コード の順番を守っているなら Range で指定できる。

A-z の範囲

for 文の場合、半開区間でも閉区間でも使える。

fn main() {
    for c in 'A'..'z' {
        print!("{}", c);
    }
    // ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy
    println!();
    for c in 'A'..='z' {
        print!("{}", c);
    }
    // ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz
}

パターンマッチングの場合、閉区間のみ使える。

    let s = String::from("abcd[@");

    match s.chars().nth(0) {  // a
        Some('A'..='z') => { println!("yes"); }
        _ => { println!("no"); }
    }
    // yes

    match s.chars().nth(4) {  // [
        Some('A'..='z') => { println!("yes"); }
        _ => { println!("no"); }
    }
    // yes
    
    match s.chars().nth(5) {  // @
        Some('A'..='z') => { println!("yes"); }
        _ => { println!("no"); }
    }
    // no

a-Z は ascii コードの順番を守れてないのでエラー

    match s.chars().nth(0) {
        Some('a'..='Z') => { println!("yes"); }
        _ => { println!("no"); }
    }
error[E0030]: lower range bound must be less than or equal to upper
 --> src/main.rs:5:14
  |
5 |         Some('a'..='Z') => { println!("yes"); }
  |              ^^^ lower bound larger than upper bound