【Capter1】クジラ飛行机さんの Rust 本を読んで Rust を勉強する
やっと手を動かして考えればよくわかる 高効率言語 Rust 書きかた・作りかた が届いたので、あらためて Rust を勉強しようと思う。
モチベーション
- The Rust Programming Language 日本語版でシンプルに文法を学んだ。資料はとても分かりやすかったが、トレイトやライフタイムなど Rust 独特の記法についての理解が浅かったと感じた。これらの知識を深めるために本を活用したい。
- Rust が CLI ツールを作成するのにとても良いということは分かったものの、ほかの用途での利用イメージが湧かなかったため、本を活用してイメージを広げたい。
- Pandas と比較して Rust での CSV パースは記法の難しさの一方で、パフォーマンスは逆に低いようだったので、自分でパフォーマンスを向上したい(Pandas の内部実装が C++だから?)
- 画像処理など Flutter アプリケーションのボトルネックになりそうな部分を Rust でカバーしたい。
- 外部ライブラリのドキュメントの読み方がイマイチわからないので、読めるようになりたい。
1 章の学習
まず、p66 までの部分で for ループと if の表現を復習。
Python と比較しながら解説していくため、非常に理解しやすい形になっていてよい。
この時点では特に記法の不明点等はない。
rust
fn main() {// for ループは .. を使って表現し、条件に()が不要for y in 1926..2026 {// print は改行を含まないprint!("西暦{}年 = ", y);if(y < 1989){println!("昭和{}年", y-1926+1);}else if(y == 1989){println!("平成元年");}else if(y < 2019){println!("平成{}年", y-1989+1);} else if(y == 2019){println!("令和元年");} else {println!("令和{}年", y-2019+1);}}}
1-9 シーザー暗号について
文字コード(i16)と文字列リテラルをasでカンタンにキャストできる。
ちなみに、ユニコードを取得したいときはu32にキャストすると良い。
rust
fn encrypt(text:&str, shift:i16) -> String{let code_a = 'a' as i16; // 'a'の文字コードを取得しているlet code_z = 'z' as i16;let mut result = String::new();//文字列リテラル.chars()で一文字づつ取り出すことができる。for ch in text.chars() {let code = ch as i16; // シーザー暗号とは文字列コードをズラすことなので、i16にキャストしている。if code_a <= code && code <= code_z {let new_code = (code - code_a + shift + 26 ) % 26 + code_a;result.push(new_code as u8 as char);}}return result;}fn main(){let result = encrypt("abcdefghijklmnopqrstuvwxyz", 1);println!("{}", result);}
クロージャー
クロージャーを定義すると、処理をカンタンに表現できる
rust
let x2 = |x| x*2;println!("{}", x2(2)); // 4
クロージャーでシーザー暗号を効率的に実装
クロージャーはなんだか方程式みたい。
未定義の c を使って、計算式を先に定義している感じ。
rust
fn encrypt(text:&str, shift:i16) -> String{let a = 'a' as i16;let is_as = |c| 'a' <= c && c <= 'z';let conv = |c| (((c-a+shift+26)%26+a) as u8) as char;let enc = |c| if is_as(c) { conv(c as i16) } else { c };return text.chars().map(|c| enc(c)).collect();}
100 個の素数を求める
rust
fn is_prime(n: usize) -> bool {for i in 2..n {if n % i == 0 {return false;}}return true;}fn get_primes(prime: &mut [usize; 100]) {let mut i = 2;let mut count = 0;while count < 100 {if is_prime(i) {prime[count] = i;count += 1;}i += 1;}}fn main() {let mut prime = [0; 100];get_primes(&mut prime);println!("{:?}", prime);}
**get_prime()**の実装の特徴は、primeを参照で渡しているところ。
この場合、prime自体が関数内部で書き変えられる。
usize 型
ポインタと同じサイズの符号なし整数(64 ビット環境では u64 と同じ)
長さが決まっている配列変数の宣言
rust
//長さ固定の場合let mut prime = [初期値 ; 配列要素数]//長さが変わる場合は可変配列のベクターを使うlet prime = vec![1,2,3,4,5]
三項演算子っぽい書き方について
Rust には三項演算子はない。
でも if else を使ってかなり似た記述が可能なので、下記にメモしておく。
rust
let x = if 条件 { 真の時の値 } else { 偽の時の値 };