Rust Slice(スライス)型

スライス(Slice)は、データ値に対する部分参照です。

スライスという名前は、生物の授業でよく出てきます。サンプル用のプレパラートを作るとき、生物の体から切片を取り出して、顕微鏡で観察します。Rust のスライスもだいたい同じ考え方です。ただし、データから参照を切り出すという点が違います。

文字列スライス

最も簡単で、最もよく使われるデータスライス型は、文字列スライス(String Slice)です。

例

fn main() {
    let s = String::from("broadcast");

    let part1 = &s[0..5];
    let part2 = &s[5..9];

    println!("{}={}+{}", s, part1, part2);
}

実行結果:

broadcast=broad+cast

上の図は、文字列スライスの仕組みを説明しています(注:Rust の文字列型は、メモリ上の文字の開始位置とその長さを実際に記録しています。今はとりあえずこの点を理解しておいてください)。

使用..範囲を表す構文は、ループの章で出てきました。x..y表す[x, y)の数学的な意味..両側にオペランドがなくても構いません:

..y 等价于 0..y
x.. 等价于位置 x 到数据结束
.. 等价于位置 0 到结束

注意:今のところ、エンコーディングの問題があるため、文字列には英語以外の文字をできるだけ使わないでください。具体的な理由は「文字列」の章で説明します。

スライスによって参照されている文字列は、その値を変更することが禁止されています:

例

fn main() {
    let mut s = String::from("サンプル");
    let slice = &s[0..3];
    s.push_str("yes!"); // エラー
    println!("slice = {}", slice);
}

このプログラムは正しくありません。

s は部分的に参照されているため、その値を変更することはできません。

実際、今までなぜ毎回文字列を使うときにこのように書くのか、きっと疑問に思っているでしょう、String::from("サンプル")、直接書く"サンプル"のはダメですか?

こうなった以上、この2つの概念の違いを区別しなければなりません。Rust にはよく使われる文字列型が2つあります:str と String です。str は Rust のコア言語型であり、この章でずっと説明してきた文字列スライス(String Slice)で、通常は参照の形(&str)で現れます。

ダブルクォーテーションで囲まれた文字列定数の型は、すべて&str:

let s = "hello";

ここでの s は &str 型の変数です。

String 型は Rust 標準ライブラリが提供するデータ型で、機能がより充実しています。文字列の追加やクリアなどの実用的な操作をサポートしています。String と str は、どちらも文字の開始位置属性と文字列の長さ属性を持っているほかに、容量(capacity)属性も持っています。

String と str はどちらもスライスをサポートしており、スライスの結果は &str 型のデータになります。

注意:スライスの結果は参照型でなければなりませんが、開発者はこれを自分で明示する必要があります:

let slice = &s[0..3];

String を &str に変換する簡単な方法があります:

let s1 = String::from("hello");
let s2 = &s1[..];

非文字列スライス

文字列以外にも、他のいくつかの線形データ構造がスライス操作をサポートしています。例えば配列:

例

fn main() {
    let arr = [1, 3, 5, 7, 9];
    let part = &arr[0..3];
    for i in part.iter() {
        println!("{}", i);
    }
}

実行結果:

1
3
5
その他の拡張