$30 off During Our Annual Pro Sale. View Details »

Rust入門以前:発表版

 Rust入門以前:発表版

第十回 カーネル/VM探検隊の発表で使ったスライド。

動画URL: https://www.youtube.com/watch?v=i17doLVXlYU

Masanori Ogino

May 25, 2014
Tweet

More Decks by Masanori Ogino

Other Decks in Programming

Transcript

  1. 想定している聴衆 簡単な C 言語のコードを読める (他の言語の話も登場するが、知らなくても OK) コンピュータと OS の構成や役割について知っている (情報系の学部一年生が学ぶであろう範囲で十分。

    本で言うと共立出版『情報・電子入門シリーズ』とか オーム社『IT Text シリーズ』 『ディジタル作法』辺り) 知らない文法のコードが見えても怖気づかない (そこまで奇抜な文法ではないが、C 言語とは少し違う) Masanori Ogino (@omasanori) Rust 入門以前
  2. OS があるとは限らない たとえば、 ファイル I/O → ファイルシステムは存在しないかも ネットワーク I/O →

    ネットワークスタックは存在しないかも メモリの割り当て → malloc(3) は存在しないかも マルチタスク(スレッド) → スケジューラは存在しないかも Masanori Ogino (@omasanori) Rust 入門以前
  3. なぜ Rust は生まれたのか? Graydon Hoare 曰く、 他のプログラミング言語で知られ、また愛されている 多くの明白に良いアイデアが、広く使われている システム言語には取り込まれていないか、 非常に貧弱な(安全でなく、並行性になじまない)

    メモリモデルを持つプログラミング言語に 組み込まれている。 出典: http://www.infoq.com/news/2012/08/Interview-Rust 翻訳・強調は筆者による。 Masanori Ogino (@omasanori) Rust 入門以前
  4. C のポインタ void do_something(my_state_t *state) { // state の NULL

    チェックは呼び出し側の責任? for (size_t i = 0; i < state->chunks_count; ++i) { // chunks[i] は NULL でないと保証されている? do_that(state->chunks[i]->heap); // do_that は state->chunks[i]->heap の // NULL チェックをしているのだろうか? } } 誰かが NULL チェックをしなければならない … 誰が?(cf. 防御的プログラミング) Masanori Ogino (@omasanori) Rust 入門以前
  5. Rust のポインタ Rust には三種類のポインタが存在する 占有ポインタ (owning pointer) 参照 (reference) 生ポインタ

    (raw pointer) →このセクションでは説明しない (他にも Rc<T>や Arc<T>、Gc<T>などがある。 しかし、今回は説明しない。Gc<T>は未だに本来意図した実装になっていないし… ) Masanori Ogino (@omasanori) Rust 入門以前
  6. 占有ポインタ // int 型の値をヒープ上に確保する let a: Box<int> = box 10;

    println!("a = {}", a); //=> a = 10 被占有ボックスはヒープ上に置かれる Masanori Ogino (@omasanori) Rust 入門以前
  7. 占有ポインタ // a の参照先の所有権が b に移動 let b: Box<int> =

    a; // a はもはや何も占有していないので // 次のコードはコンパイルエラー // println!("a = {}", a); println!("b = {}", b); //=> b = 10 参照のコピー(シャローコピー)は所有権の移動 Masanori Ogino (@omasanori) Rust 入門以前
  8. 占有ポインタ let c: Box<int> = b.clone(); // b と c

    は別の領域を占有している println!("b = {}", b); //=> b = 10 println!("c = {}", c); //=> c = 10 参照先を含めたコピー(ディープコピー)は 独立したポインタと値の組を作る Masanori Ogino (@omasanori) Rust 入門以前
  9. 参照 let a: int = 10; let b: &int =

    &a; println!("a = {}", a); //=> a = 10 println!("b = {}", b); //=> b = 10 &var で var への参照 Masanori Ogino (@omasanori) Rust 入門以前
  10. 参照 let a: Box<int> = box 10; // a: Box<int>

    // *a: int // &*a: &int let b: &int = &*a; // a は所有権を失っていない println!("a = {}", a); //=> a = 10 println!("b = {}", b); //=> b = 10 Masanori Ogino (@omasanori) Rust 入門以前
  11. 占有ポインタと参照 参照を作ってから所有権を移動したらどうなる? fn main() { // 次のコードを考えてみよう let a: Box<int>

    = box 10; let b: &int = &*a; // a が占有する int 型の値を参照 let c: Box<int> = a; // a の持つ所有権は c に移動する // 値の所有者が変わっても b は有効なのか? } Masanori Ogino (@omasanori) Rust 入門以前
  12. 占有ポインタと参照 Box<T> T 占有ポインタ (owning pointer) 被占有ボックス (owned box) &T

    参照 (reference) Box<T> 所有権の移動 ? Masanori Ogino (@omasanori) Rust 入門以前
  13. 占有ポインタと参照 実際にやってみると ref2.rs:5:9: 5:10 error: cannot move out of `a`

    because it is borrowed ref2.rs:5 let c: Box<int> = a; // a の持つ所有権は c に移動する ^ ref2.rs:4:20: 4:22 note: borrow of `*a` occurs here ref2.rs:4 let b: &int = &*a; // a が占有する int 型の値を参照 ^~ error: aborting due to previous error 参照に値を「貸して」いる間は 所有権を移動できない Masanori Ogino (@omasanori) Rust 入門以前
  14. Rust のデストラクタ fn main() { { let a: Box<int> =

    box 10; println!("a = {}", a); //=> a = 10 } // ここに来る時点で a の参照先は解放されている } Masanori Ogino (@omasanori) Rust 入門以前
  15. クイズ 次のコードはどうなる? fn main() { let a: &int; { let

    b: Box<int> = box 10; a = &*b; } // b の有効範囲はここまで println!("a = {}", a); // use-after-free の予感! } Masanori Ogino (@omasanori) Rust 入門以前
  16. const vs. mut: Rust の場合 再代入・変更を許す場合は mutを付ける (mut を only

    にしようという提案がある。 変更の可否は所有権や参照の有無によって変化するため。 ) Masanori Ogino (@omasanori) Rust 入門以前
  17. const vs. mut: どちらが良いか for (int i = 1; i

    < 10; ++i) { int square = i * i; printf("%d\n", square); } const を付けなくても動くコードに const を付けたい人? Masanori Ogino (@omasanori) Rust 入門以前
  18. const vs. mut: どちらが良いか for i in range(1, 10) {

    let square = i * i; println!("{}", square); } mut を付けなくても動くコードに mut を付けたい人? Masanori Ogino (@omasanori) Rust 入門以前
  19. const vs. mut: どちらが良いか for i in range(1, 10) {

    let mut square = i * i; println!("{}", square); } Masanori Ogino (@omasanori) Rust 入門以前
  20. const vs. mut: どちらが良いか mut-to-imut.rs:8:13: 8:23 warning: variable does not

    need to be mutable, #[warn(unused_mut)] on by default mut-to-imut.rs:8 let mut square = i * i; ^~~~~~~~~~ rustcに冗談は通じない (警告を無効にしない限り) (gcc や clang にある同等の警告オプションを ご存じの方はいらっしゃいませんか。 -Wall -Wextra では警告されませんでした) Masanori Ogino (@omasanori) Rust 入門以前
  21. C のポインタ: dangling pointer bugs /* 出典:"A 30-minute Introduction to

    Rust" */ int* dangling(void) { int i = 1234; return &i; } int add_one(void) { int* num = dangling(); return *num + 1; } Masanori Ogino (@omasanori) Rust 入門以前
  22. C のポインタ: use-after-free bugs void use_after_free(void) { int *data =

    malloc(sizeof(struct something)); if (!data) return; /* ... */ free(data); printf("%d\n", data->count); } Masanori Ogino (@omasanori) Rust 入門以前
  23. C のポインタ: double free bugs void double_free(void) { int *data

    = malloc(sizeof(struct something)); if (!data) goto error; /* ... */ free(data); error: /* ... */ free(data); } Masanori Ogino (@omasanori) Rust 入門以前
  24. 生存期間 // 出典: "A 30-minute Introduction to Rust" fn dangling()

    -> &int { let i = 1234; return &i; } fn add_one() -> int { let num = dangling(); return *num + 1; } fn main() { add_one(); } Masanori Ogino (@omasanori) Rust 入門以前
  25. 生存期間 dangling.rs:4:13: 4:14 error: `i` does not live long enough

    dangling.rs:4 return &i; ^ dangling.rs:2:23: 5:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 2:22... dangling.rs:2 fn dangling() -> &int { dangling.rs:3 let i = 1234; dangling.rs:4 return &i; dangling.rs:5 } dangling.rs:2:23: 5:2 note: ...but borrowed value is only valid for the block at 2:22 dangling.rs:2 fn dangling() -> &int { dangling.rs:3 let i = 1234; dangling.rs:4 return &i; dangling.rs:5 } error: aborting due to previous error Masanori Ogino (@omasanori) Rust 入門以前
  26. 式としての制御構造 fn is_even_stmt(n: int) -> bool { if n %

    2 == 0 { return true; } else { return false; } } if文 Masanori Ogino (@omasanori) Rust 入門以前
  27. 式としての制御構造 fn is_even_expr(n: int) -> bool { return if n

    % 2 == 0 { true } else { false }; } if式 Masanori Ogino (@omasanori) Rust 入門以前
  28. 代数的データ型 集合 + 集合 = 集合(直和) 集合 × 集合 =

    集合(直積) Masanori Ogino (@omasanori) Rust 入門以前
  29. 代数的データ型 型 + 型 = 型(直和型) 型 × 型 =

    型(直積型) Masanori Ogino (@omasanori) Rust 入門以前
  30. 代数的データ型 // From src/libcore/result.rs // Result<T, E>は T か E

    の型の値を // 取れる→直和型 pub enum Result<T, E> { Ok(T), Err(E) } 列挙型 + コンストラクタで 直和型が表せる Masanori Ogino (@omasanori) Rust 入門以前
  31. 代数的データ型 // Pair<T1, T2>は T1 と T2 の // 値の組を作る→直積型

    enum Pair<T1, T2> { P(T1, T2) } 列挙型 + コンストラクタで 直積型が表せる (Rust にはタプル(値の組)を表す型を直接サポートしている) Masanori Ogino (@omasanori) Rust 入門以前
  32. パターンマッチ fn factorial(n: int) -> int { // uses implicit

    return match n { 0 => 1, n => n * factorial(n - 1) // or, // n if n != 0 => n * factorial(n - 1) } } 数でも Masanori Ogino (@omasanori) Rust 入門以前
  33. 他のプログラミング言語の良いアイデア: ML あと、let などの文法要素も ML 由来 (先日、The Definition of Standard

    ML の著者の一人は Rust を ML-like languages の一つとして紹介していた) Masanori Ogino (@omasanori) Rust 入門以前
  34. なぜ Rust は生まれたのか? Graydon Hoare 曰く、 Our target audience is

    "frustrated C++ developers". I mean, that's us. So if you are in a similar situation we're in, repeatedly finding yourself forced to pick C++ for systems-level work due to its performance and deployment characteristics, but would like something safer and less painful, we hope we can provide that. 出典: http://www.infoq.com/news/2012/08/Interview-Rust 強調は筆者に よる。 Masanori Ogino (@omasanori) Rust 入門以前