第64回です。前回はこちら。
[第64回の様子]
2023/01/18に第64回を開催した。
内容としてはRust By Example 日本語版19. 標準ライブラリの型の「19.3. 文字列」の後半を最後まで取り組んだ。
参加者は自分を入れて3人。今日は勉強会終了後のSlackでの発言も多めだったので良き。
[学んだこと]
- 19.3. 文字列
- Literals and escapesのパートからスタート。
- Rustで文字列を定義する時に、特殊文字をエスケープする方法がいくつかある
- 基本的にはバックスラッシュ(
\)でエスケープできる - バックスラッシュ自体が必要なときは連続させることになる:
\\ - この辺は他のプログラミング言語と変わらない
- "で囲まれた文字列でも'で囲まれた文字でもエスケープは同様
let byte_escape = "I'm writing \x52\x75\x73\x74!";
println!("What are you doing\x3F (\\x3F means ?) {}", byte_escape);
// What are you doing? (\x3F means ?) I'm writing Rust!
- ユニコードのコードポイントを利用して
\u{コードポイント}のようにも書ける
let unicode_codepoint = "\u{211D}"; let character_name = "\"DOUBLE-STRUCK CAPITAL R\""; println!("Unicode character {} (U+211D) is called {}", unicode_codepoint, character_name ); // Unicode character ℝ (U+211D) is called "DOUBLE-STRUCK CAPITAL R"
- 複数行文字列の場合、通常インデントと改行がそのまま出力されるが、エスケープすることでどちらも無視した出力となる
let long_string = "String literals
can span multiple lines.
The linebreak and indentation here ->\
<- can be escaped too!";
println!("{}", long_string);
// String literals
// can span multiple lines.
// The linebreak and indentation here -><- can be escaped too!
let raw_str = r"Escapes don't work here: \x3F \u{211D}";
println!("{}", raw_str);
// エスケープされず以下のように出力される
// Escapes don't work here: \x3F \u{211D}
- 生文字列中でダブルクオートを利用する場合、以下のように前後にシャープを置く
let quotes = r#"And then I said: "There is no escape!""#;
println!("{}", quotes);
// And then I said: "There is no escape!"
- 生文字列中で#が必要な場合は、連続する#より1個多い#を前後に置く
let longer_delimiter = r###"A string with "# in it. And even "##!"###;
println!("{}", longer_delimiter);
// A string with "# in it. And even "##!
- テキストでは前後につけるデリミタの#は65536個までと書かれているが、実際に試してみると255個まででコンパイルエラーがでた
error: too many `#` symbols: raw strings may be delimited by up to 255 `#` symbols, but found 259 --> src/main.rs:12:28 | 12 | ... = r###################################################################################################################################################################################################################################################################"A string with "# in it. And even##"#################################################################################################################################################################################################################################################################... | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- バイト文字列を使うと、&strではなくUTF-8の配列として扱える
let bytestring: &[u8; 21] = b"this is a byte string";
println!("A byte string: {:?}", bytestring);
// A byte string: [116, 104, 105, 115, 32, 105, 115, 32, 97, 32, 98, 121, 116, 101, 32, 115, 116, 114, 105, 110, 103]
let escaped = b"\x52\x75\x73\x74 as bytes";
println!("Some escaped bytes: {:?}", escaped);
// Some escaped bytes: [82, 117, 115, 116, 32, 97, 115, 32, 98, 121, 116, 101, 115]
let escaped = b"\u{211D} is not allowed";
println!("Some escaped bytes: {:?}", escaped);
// 以下のコンパイルエラー
error: unicode escape in byte string
--> src/main.rs:13:21
|
13 | let escaped = b"\u{211D} is not allowed";
| ^^^^^^^^ unicode escape in byte string
|
= help: unicode escape sequences cannot be used as a byte or in a byte string
- 生文字列同様、生バイト文字列も利用できる
let raw_bytestring = br"\u{211D} is not escaped here";
println!("{:?}", raw_bytestring);
// [92, 117, 123, 50, 49, 49, 68, 125, 32, 105, 115, 32, 110, 111, 116, 32, 101, 115, 99, 97, 112, 101, 100, 32, 104, 101, 114, 101]
// 改行も利用可能
let _quotes = br#"You can also use "fancier" formatting, \
like with normal raw strings"#;
- バイト文字列をstrに変換するには以下のようにする
use std::str;
let raw_bytestring = br"\u{211D} is not escaped here";
if let Ok(my_str) = str::from_utf8(raw_bytestring) {
println!("And the same as text: '{}'", my_str);
}
// And the same as text: '\u{211D} is not escaped here'
use std::str; // SHIFT-JISで「ようこそ」 let shift_jis = b"\x82\xe6\x82\xa8\x82\xb1\x82\xbb"; // UTF-8には変換できない match str::from_utf8(shift_jis) { Ok(my_str) => println!("Conversion successful: '{}'", my_str), Err(e) => println!("Conversion failed: {:?}", e), }; // Conversion failed: Utf8Error { valid_up_to: 0, error_len: Some(1) }
- SJISなどエンコードが必要な場合はencodingsクレートを利用するとよいらしい
- WindowsのCLIアプリを作る場合など、デフォルトの文字コードがSJISなので色々困りそう...という話題で盛り上がった。
[まとめ]
モブプログラミングスタイルでRust dojoを開催した。
短い章だと思ったけどなかなか骨のある章だった...文字列、奥が深い。
今週のプルリクエストはこちら。