Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

プログラミング言語Rustのご紹介

Yuki Toyoda
August 22, 2020
7.5k

 プログラミング言語Rustのご紹介

Zli x サイバーエージェント合同LT会にて発表した内容です。

Yuki Toyoda

August 22, 2020
Tweet

Transcript

  1. ⾃⼰紹介 yuki (Twitter: @helloyuki_ ) 社会⼈ 6 年⽬(まだ 20 代!)

    Rust.Tokyo & RustFest Global オーガナイザー 共著『実践 Rust プログラミング⼊⾨』 使える⾔語: Japanese, English (UK), French 2020-08-22 Zli × サイバーエージェント 合同LT
  2. ⾃⼰紹介 Rust を使いはじめたきっかけ 同時期に Go もはやりだしていた。 ⼀応先輩に勧められて両⽅触った。 Java の抽象化の機構がすごく好きだったので、Rust の抽象化の機構もしっくりき

    た。 私はものが動くよりもプログラムやアルゴリズムが美しいことの⽅が好きなん だと思う なので、それ以来 Rust を使⽤している。 2020-08-22 Zli × サイバーエージェント 合同LT
  3. Rust とは? 2015 年にリリースされたシステムプログラミング⾔語。 A language empowering everyone to build

    reliable and efficient software (Rust Official) but especially folks who didn't think systems programming was for them (Ashley Williams) fn main() { let user_name = "Yuki"; println!("Hello, World!: {}", user_name); } 2020-08-22 Zli × サイバーエージェント 合同LT
  4. ⾔語としての特徴 とにかく速い。 平均して Go より速い。Java より速い。C/C++ 並の速度が出る。 速い上にゼロコスト抽象化によって、コードのきれいさを⼀切諦めずに実装でき る。 DX

    と速さがトレードオフにならない。 実⾏時に未定義動作(UB; Undefined Behaviour)が発⽣しない。 use-after-free を始めとするメモリ安全でない実装はコンパイル時に弾く。 強⼒な型システムによって、並⾏処理時に発⽣するデータ競合もコンパイル時に弾 く。 2020-08-22 Zli × サイバーエージェント 合同LT
  5. 利⽤事例 国外: Google, Amazon, Facebook, Microsoft, etc 国内: FORCIA, CADDi,

    DeNA, LayerX, OPTiM, etc 海外では、 Go や Node.js でできた既存システムからの移⾏事例が多い。 国内では、移⾏事例より最初から Rust を⼊れてみた系が多い。 2020-08-22 Zli × サイバーエージェント 合同LT
  6. 将来性 Chromium の⼀部コンポーネントへの導⼊が検討されはじめている? Amazon や Microsoft はすでに公式に Rust を使⽤したプロダクトを作ったことを発表し ている。

    Linux への導⼊の噂。 Rust Foundation の設⽴を 2020 年中に⾏うことが発表された。 Rust は次の 40 年のための⾔語 Rust: A Language for the Next 40 Years - Carol Nichols https://www.youtube.com/watch?v=A3AdN7U24iU 2020-08-22 Zli × サイバーエージェント 合同LT
  7. ⾔語としてもう少しがんばる必要があると思っているところ すべての⾔語は何かしらのトレードオフの上に成り⽴っているので、思うところを書く。 Bjarne Stroustrup ⽒の講演を 2 年前に東京⼤学で聞いたのだが、その際にこんな質問が あった。 質問者「Rust についてどう思っていますか?C++

    と似たことを実現しようとして いますが」 Bjarne さん「よく知らないんだけど、C++ には⻑い歴史によって積み重ねられたエ コシステムがある。それを揃えるのは⼤変だろうね」 同意⾒。 2020-08-22 Zli × サイバーエージェント 合同LT
  8. ⾔語としてもう少しがんばる必要があると思っているところ エコシステムの充実と成熟が急務であり、かつもっともユーザーに求められていること でもある。 とくに Web 系の⼈間からすると、Spring (Java)、Akka (Scala)、Rails (Ruby) クラ

    スの強⼒なフレームワークがないように思う。 actix-web が有⼒ではある。 ただでさえ学習コストが⾼い⾔語だが、まだまだチュートリアルが少ない。 中級者以上のチュートリアルの充実が急務。⼊⾨編はかなり多く存在するが、中級 者向け、上級者向けワークアラウンドとなるとまだまだない。 『Effective Rust』の執筆が待たれる。 ただ、これらはユーザーが増えていくと⾃然と解決するものなので、Rust のファンを作 るのが⼤事 2020-08-22 Zli × サイバーエージェント 合同LT
  9. 参照 ダングリングポインタなどの危険な操作はコンパイルエラーになる。 fn definitly_one() -> &i32 { // この変数のスコープは関数末尾まで。 let

    i = 1; // ローカル変数の参照を返す = danglig pointer // これは後述のライフタイムと関連して、コンパイルエラーとして検出される。 &i } 2020-08-22 Zli × サイバーエージェント 合同LT
  10. 所有権 Rust では、値には 1 つの所有者がいる。所有権がなくなると値は破棄される。 値は借⽤という機能によって貸し借りできる。 fn main() { //

    メモリを確保する。 let text1 = String::from("text"); // text1 はこの時点で解放され、新たに text2 ⽤のメモリが確保される。 let text2 = text1; // 解放されている箇所にアクセスしているので、これはコンパイルエラーとして検出される。 println!("{}", text1); } 2020-08-22 Zli × サイバーエージェント 合同LT
  11. 所有権 コンパイルエラーは次のように出る。 error[E0382]: borrow of moved value: `text1` --> src/main.rs:4:20

    | 2 | let text1 = String::from("Hello, world"); | ----- move occurs because `text1` has type `std::string::String`, which does not implement the `Copy` trait 3 | let text2 = text1; | ----- value moved here 4 | println!("{}", text1); | ^^^^^ value borrowed here after move 2020-08-22 Zli × サイバーエージェント 合同LT
  12. 所有権 スコープを抜けても、所有権は移動する。 { // この時点で text は有効になる。 let text =

    "Hello"; } // スコープが終了し、text はもう有効ではなくなる。 2020-08-22 Zli × サイバーエージェント 合同LT
  13. 所有権 何が起きているのか 次のコードを… // S(1) を t に束縛する。 let t

    = S(1); // 想定では、t の値は a にムーブする。 let a = t; 2020-08-22 Zli × サイバーエージェント 合同LT
  14. ライフタイム ダングリングポインタの回避のための仕組みで、参照のスコープを解析する。 ライフタイムのおかげでファイルディスクリプタなどの破棄も、任せておける。 { let r; { let x =

    5; // r は x への参照をもつが… r = &x; } // x はこのスコープを抜ける瞬間にムーブ。 // スコープ外の参照を使⽤しようとしている→ ライフタイム制約違反 println!("r: {}", r); } 2020-08-22 Zli × サイバーエージェント 合同LT
  15. Borrow Checker 所有権やライフタイムは、コンパイル時に違反が検出される。 AST → HIR → MIR → LLVM

    IR → Machine Code の順で Rust コンパイラはコンパイル していく。 MIR という中間⾔語でこのあたりの操作(Borrow Checker)が確認されている。 2020-08-22 Zli × サイバーエージェント 合同LT
  16. Borrow Checker 下記コードの MIR を読んでみる。 fn main() { let r;

    { let x = 11; r = x; } } 2020-08-22 Zli × サイバーエージェント 合同LT
  17. Borrow Checker 読みやすさのために出⼒内容を⼀部削除している。 fn main() -> () { let mut

    _0: (); // return place in scope 0 at src/main.rs:1:11: 1:11 let _1: i32; // in scope 0 at src/main.rs:2:9: 2:10 scope 1 { debug r => _1; // in scope 1 at src/main.rs:2:9: 2:10 let _2: i32; // in scope 1 at src/main.rs:4:13: 4:14 scope 2 { debug x => _2; // in scope 2 at src/main.rs:4:13: 4:14 } } bb0: { StorageLive(_1); // scope 0 at src/main.rs:2:9: 2:10 StorageLive(_2); // scope 1 at src/main.rs:4:13: 4:14 _2 = const 11i32; // scope 1 at src/main.rs:4:17: 4:19 _1 = const 11i32; // scope 2 at src/main.rs:5:9: 5:14 _0 = const (); // scope 1 at src/main.rs:3:5: 6:6 StorageDead(_2); // scope 1 at src/main.rs:6:5: 6:6 StorageDead(_1); // scope 0 at src/main.rs:7:1: 7:2 return; // scope 0 at src/main.rs:7:2: 7:2 } } 2020-08-22 Zli × サイバーエージェント 合同LT
  18. デフォルトが不変(イミュータブル) 何も指定せず変数を宣⾔(Rust では束縛という)すると不変になる。 可変にするには、明⽰的に書く必要がある。 不変な変数に可変な操作を⾏おうとすると、コンパイルエラーになる。 fn main() { // x

    は不変な変数として宣⾔される let x = 5; // the value is 5 println!("the value is {}", x); // 不変で束縛した変数に新しい値を代⼊しようとした。 // コンパイルエラーになる。 x = 6; println!("the updated value is {}", x); } 2020-08-22 Zli × サイバーエージェント 合同LT
  19. デフォルトが不変(イミュータブル) 先ほどのコードは、変数が可変な事を⽰す let mut と書くことによって動作させられ る。 fn main() { let

    mut x = 5; println!("the value is {}", x); x = 6; println!("the updated value is {}", x); } 2020-08-22 Zli × サイバーエージェント 合同LT
  20. 代数的データ型とパターンマッチング Rust ではいたるところに代数的データ型(ADT; Algebraic Data Types)が登場する。 代数的データ型を組み合わせながら実装を進めていく。 #[derive(Clone)] pub enum

    Token { Number(i32), BoolValue(bool), Var(String), Add(Box<Token>, Box<Token>), Multiply(Box<Token>, Box<Token>), LessThan(Box<Token>, Box<Token>), } 2020-08-22 Zli × サイバーエージェント 合同LT
  21. 代数的データ型とパターンマッチング パターンマッチングして、条件に応じた処理を書ける。 impl Token { pub fn is_reducible(&self) -> bool

    { use Token::*; match *self { Number(_) => false, BoolValue(_) => false, Var(_) => true, Add(_, _) => true, Multiply(_, _) => true, LessThan(_, _) => true, } } } 2020-08-22 Zli × サイバーエージェント 合同LT
  22. 代数的データ型とパターンマッチング fn main() { let ans_result = less_than_hundred_add(1, 2); match

    ans_result { Ok(ans) => println!("{}", ans), Err(err) => eprintln!("{:?}", err), } } #[derive(Debug)] struct CalcErr; fn less_than_hundred_add(left: i32, right: i32) -> Result<i32, CalcErr> { if left > 100 || right > 100 { Err(CalcErr) } else { Ok(left + right) } } 2020-08-22 Zli × サイバーエージェント 合同LT
  23. Rust.Tokyo ⽇本初の Rust カンファレンスを 2019 年 10 ⽉ 26 ⽇に開催した。

    会場の都合で 200 名までの参加だ ったが、肌感ではそれ以上の⼈数 が集まりそうだった。 2020-08-22 Zli × サイバーエージェント 合同LT
  24. はじめよう $ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

    $ cargo new hello_rust --bin $ cd hello_rust $ cargo run Hello, world! 2020-08-22 Zli × サイバーエージェント 合同LT
  25. RustFest Global やるよ 今年は Rust.Tokyo はコロナの影響で中⽌の判断をした。 RustFest と Rust.Tokyo が合流し、グローバルカンファレンスを開く。

    ⽇本語で話していただいて OK(事前録画が必要などの制約はあり)。 APAC 想定なので、中国(本⼟、台湾、⾹港)、韓国、マレーシア、オーストラリアな どからも期待。 RustFest goes Global: https://blog.rustfest.eu/rustfest-goes-global 2020-08-22 Zli × サイバーエージェント 合同LT