Rustに入門したので、適宜HaskellのこれはRustのこれ、ということをここに蓄積していって、個人的なチートシートにする。

Borrow と Ownership

  • 基本的に Region Monad と線型型(呼ばなくても良いので正確にはアファイン型)が組込みだと思えばよい。
    • { から } までの間でスコープが区切られ、スコープごとに Drop (=free)がされる。

プロジェクト管理

  • Stack に当たるのが cargo
  • stack.yamlCargo.toml
  • コードは src 直下固定。src/main.rsMain.hs 相当で、src/lib.rs がライブラリのルートに当る。

モジュールシステム

  • 一つの .rs ファイル内で複数のモジュールを、ネストして定義出来る。
  • mod a; のように定義を省略した場合、a.rsの内容がモジュール a の定義として扱われる。
  • foo::bar::buz に当るファイルは src/foo/bar/buz.rs
    • このファイルの存在下では、foo::bar に当るのは src/foo/bar/mod.rs
  • Haskellの import に近いのは use
    • use a::b::c と宣言しておくと、以後モジュール a::b 以下の定義は b::fun などと呼び出せるようになる。

字句構造

  • 基本的に全て式だが、() 返すのが文。
  • 関数の最後で値を返す際には return は不要。
  • ただし式の最後に ; を付けると文になってしまうので、生の式で値を返す場合は ; を付けないように。
  • Haskell と違い、変数はバシバシ shadowing していく文化。
    • 注意:Shadowing された変数にアクセスする方法はないが、shadowing されてもスコープが区切られなければ Drop はされない。
  • コメントは一行コメントのみ:// これはコメントです
  • ここに入れていいのかわからないが、インデントは4スペース。

変数束縛

  • let a: T = b は不変変数宣言。
  • let mut a: T = b は可変変数。
  • static A: T = b は定数宣言。
  • static 以外は型註釈はある程度省略出来る。
  • あとは & とか ref とかの修飾子が適宜つく。

制御構造

データ型

  • Int16, Int32, Int64, Word16, Word32, Word64 に当るのが i16, i32, i64, u16, u32, u64。 ポインタアドレス等、アーキテクチャ依存の整数型(IntWord)は isize (符号付) や usize (符号無)。
  • structenum が Haskell の datanewtype に当る。

  • struct は直積型、enum は直和型。
    • enumの各コンストラクタをvariantと言う。
    • フィールドラベルのついた struct F { a: i64 } と、ついていないタプル構造型 struct F(i64) は全く違うもの。
  • 再帰型は Box<a> などに包んで間接的に参照の形で持つ。
    • フィールドの値や関数の引数は、メモリ上でのサイズが確定していないといけないので。
  • コンストラクタは Enum::A のように呼ぶ。
    • ここでも use が使え、use Struct::*use Enum::* のようにすると、単にA(12)B { val: 12, dull: 54 } のように呼べる。
  • NamedFieldPuns 拡張のようなことが出来、Foo { bar } とやるとスコープにある bar の値が barフィールドbar の値になる。
    • 逆にパターンの来る文脈で let P {x , y} = p とすればフィールド x, y の値が変数 x, y にバインドされる。
  • レコードの更新:d = D { field: a, gield: b } のとき、 Haskellでいう d { field = val } は Rust だと D { field: val, .. d } となる。
  • ベクトル:Vec<T>。リストリテラルのように作るのは vec![1,2,3]
    • 固定長ベクトルは [T; 3] のよう。

モナドと例外・失敗処理

  • モナドはない。
    • でも将来に向けて do は予約語になっているようだ。
  • 例外機構はなく、panicを使って自殺するか、後述の Result を使っていくのがよいとされているようだ。
  • Maybe a に対応するのが Option<T>NothingJust aには{.hs} には Some(a)Noneが対応。
    • Optionpanicに変換するには:
      • fromJust ma == ma.unwrap()
      • fromMaybe (error "unko") ma == ma.expect("unko")
  • Either a b に対応するのが Result<B, A>
    • Right a == Ok(a), Left b == Err(b)
    • ライブラリ毎に type MyResult<T> = Result<T, MyError> のような別名を用意している。
    • 順番に注意!Haskell の流儀では二番目の型引数が「成功」だが、Rustでは最初の型引数が成功値
    • unwrap()expect("foo")は同様に使える。
    • モナドはないが、SwiftやCoffeeScriptの ? オペレータと同じようなものがある。

      とかあったら、?が付いてる値が Err(hoge) だった場合、なんかいいかんじの変換が成されて直ちに Err が返るようになる(注:Haskellと違いRustにはearly returnがある)。
      • 但し関数定義(returnが呼べるところ)でしか使えない。
      • qnighy氏の記事によれば、nightly では do catch 構文があるようだが、stableには入ってない模様。

オーバーロード


Comments