第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を開催した。
短い章だと思ったけどなかなか骨のある章だった...文字列、奥が深い。
今週のプルリクエストはこちら。