イテレータ実装のための新キーワードgen
Rust 2024では、イテレータ実装のためのキーワードgenが予約語となりました。
genが予約語となったため、genを識別子名として使用する場合には、生識別子としてr#genとする必要があります。genが予約語とされるのは、将来的にイテレータ実装を簡便な方法で行えるようにするためです。現時点では、イテレータの実装は以下のリストのように構造体を定義し、その構造体にIteratorトレイトを実装するという手順を踏む必要があります。
struct Fractional { // 階乗計算のための構造体を準備
a: i128,
n: i128,
}
impl Iterator for Fractional { // Fractional構造体にIteratorトレイトを実装する
type Item = i128;
fn next(&mut self) -> Option<i128> { // 値取り出しのためのnextメソッドを定義
if self.a == 32 {
Some(0) // オーバフローする場合には0を返す
} else {
let x = self.n;
self.a += 1;
self.n *= self.a;
Some(x)
}
}
}
let fractional = Fractional { a: 0, n: 1 }; // Fractional構造体を初期化
for i in fractional
.take_while(|&f| f != 0) { // 0が返されるまでの間
println!("{i}");
}
これは階乗計算のためのFractional構造体を定義し、Iteratorトレイトのnextメソッドを実装、take_whileメソッドで0が返るまでの間、計算された階乗値を表示するものです。これをgenキーワードで書き直すと、以下のリストの通りになります(あくまでRFCで提案されている内容です。2024版でもコンパイルできません)。
let fractional = gen { // genブロックを定義
let mut a = 0;
let mut n = 1;
loop {
if a == 32 {
yield 0;
} else {
let x = n;
a += 1;
n *= a;
yield x; // 現在の値を出力する
}
}
}
.into_iter();
for f in fractional
.take_while(|&f| f != 0) {
println!("{f}");
}
genブロックから値を出力するには、他言語でも使われるyieldキーワードを使います。このようにgenブロックでは、イテレータの実装をよりシンプルに直感的に行えるようになる予定です。
#"abc"#形式の文字列構文などの予約
Rust 2024では、プレフィクスのない文字列構文#"abc"#と連続した#の構文が将来のために予約されました。
Rust 2024では、以下の構文が予約されます。
- #"abc"# #"123"# など
- ## ### など(間に空白が入らないこと)
#"abc"#は、ガードされた文字列リテラル構文です。ガードされた文字列リテラル構文とは、生文字列を表すr#"string"#のようにプレフィクスとして識別子を伴う文字列リテラルです。識別子の種類によって文字列リテラルの性格を指定することができます。
従来は、ガードされた文字列リテラル構文を一つのトークンとして認識しましたが、これにはプレフィクスのない場合が含まれていませんでした。将来、プレフィクスのないガードされた文字列リテラルが意味を持つときに備えて、あらかじめ予約構文としてしまおうということです。###など、連続した#も同様に予約構文となります。
この変更は、例えばマクロ解釈において影響を受けます。従来は、#"string"#は3つのトークンに分割されましたが、Rust 2024では1つのトークンとみなされます。##なども同様で、それぞれ別のトークン(#)に分割されていたのが、1つのトークン(##)とみなされます。配布サンプルreserved-syntax(2021版対応)を実行すると、それを確認できます。
なお、Cargo.tomlのeditionキーを2024に変更するとコンパイルエラーとなります。これは、#"abc"#と###が予約構文となったためです。
