Strings(Rust)
3つの理由で詰まる
Rustエラーが出やすいから
stringsは思っているより複雑である
bytesのcollection
create/update/read
他のコレクションとのちがい
indexing
What is a String?
言語のコアには唯一のstr型があるだけ
ふつうは&strとしてつかう
string sliceはUTF-8の列に対する参照
リテラルはプログラムバイナリ
Stringは?
スタンダードライブラリであって言語のコアではない
growable, mutable, owned, UTF-8 encoded string type
ふつうにstringといったときは両方を指すString, &str
エンコードが異なる型もある
Creating a New String
code:create_new_string.rs
fn main() {
let mut s = String::new();
let data = "initial contents";
let s = data.to_string();
let s = "initial_contents".to_string();
let s = String::from("initial_contents");
println!("{}", s);
}
Updating a String
Appeinding
push_str(&self, &str)
push(&self, ch char)
Concatenation
+ format!マクロ
+はfn add(self, s: &str) -> Stringのようなものを使っているのでmoveされる
本物はgenerics
引数のsに&strではなくStringを渡せるのは"coerce"されるから
Rustはderef coercionをつかう→Chapter 15
moveされるのでコピーは起きていない
code:updating_a_string.rs
fn main() {
let mut s1 = String::new();
let s2 = "World";
s1.push_str(s2); // &strをとるのでownershipを奪わない
println!("s1 = {}, s2 = {}", s1, s2);
}
fn main() {
let mut s1 = String::new();
s1.push('h');
println!("s1 = {}", s1);
}
code:appending.rs
fn main() {
let s1 = String::from("Hello, ");
let s2 = String::from("World!");
let s3 = s1 + &s2; // s1はmoveされてこのあと使えなくなる
println!("s3 = {}", s3); // s3 = Hello, World!
}
fn main() {
let s1 = String::from("Hello, ");
let s2 = String::from("World!");
let s3 = String::from(" Rust!");
let s = s1 + &s2 + &s3;
println!("s = {}", s); // s = Hello, World! Rust!
}
fn main() {
let s1 = String::from("Hello, ");
let s2 = String::from("World!");
let s3 = String::from(" Rust!");
let s = format!("{}-{}-{}", s1, s2, s3);
println!("s = {}", s); // s = Hello, World! Rust!
println!("{}", s1); // 所有権は残っている
}
Indexing into Strings
多くの言語ではindexingできるけどRustではエラーになる
なぜ?内部表現に理由がある
len()はバイト数になる
内部表現
StringはVec<u8>のwrapper
多バイト文字でindexingしても有効な文字とは限らないのでindexing自体できなくした
O(1)でできるわけでもないのでindexingをなくした
Bytes and Scalar Values and Grapheme Clusters! Oh My!
Rustでは文字列をみる3つの見方がある:
bytes
Unicode scalar values
Slicing Strings
Methods for Iterating Over Strings
for c in "नमस्ते".chars() でunicode scalarについてiterate
for b in "नमस्ते".bytes()でbyteについてiterate
code:internal.rs
let hello = String::from("Здравствуйте");
println!("{:?}", hello.len()); // 24
code:slicing.rs
let hello = String::from("Здравствуйте");
println!("{:?}", s); // "Зд"
// let s = &hello0..1; // 実行時にpanicする! Strings Are Not So Simple: 難しい