実践Rust入門 6日目

6章頭から6章途中まで。

Rustの基本構文について。
といっても、サンプルとして既出のものがほとんど。
それぞれ補足された感じ。

結局ほとんどコードを書かずに読むだけスタイルで進めてしまった。
全構文を使って遊べる無茶なサンプルコードがあれば楽しく学べるかも。

というか、REPLが欲しい。
と思ったら、あった。
と思ったら、ビルドエラーになった。-> 課題参照

ビルド通して使ったら、遅い。
コンパイルしてそうだから仕方ない。普通にエディタで書こう。

明日からいよいよ7章の所有権に突入。
7章だけで3日くらいかかる予感。

おぼえがき
  • ブロックコメント/**/入れ子にできる -> /* /* */ */
  • 文は()を返す。文末には;を付ける。
    • 文は宣言文と式文に分解され、式文には;が省略できるものもあう
  • Rustでは値を返すためのreturnは使わないのが慣習
  • 呼び出し元に制御を返さない関数=発散する関数と呼ぶ
    • fn func() -> !{ std::process::exit(0); }
    • プロセスの終了、無限ループ、CPUを待機状態(割り込み待ち)にさせるときに使う
  • メソッドの第1引数はレシーバ(Pythonっぽい)。型は省略可
    • impl内に実装する
    • 本来は(&obj).method()という形だけどobj.method()でいいとのこと(コンパイラが頑張ってくれる)
  • 構造体などデータ型に紐付けた関数を関連関数という
    • Javaでいうクラスメソッドっぽい。インスタンスでなく型に紐付く
    • impl内に実装する。ただし、第1引数はselfにしない
    • anytype::func()で呼び出す
  • 変数のスコープは導入したブロック内{}のみ
  • 束縛は同じ名前に対して何度でもできるっぽい(シャドウィング)
  • 定数もあるconst CONST_VAL: u32 = 777;
    • Cでいうマクロ定数っぽい
    • コンパイル時に1度だけ計算。参照先にはその計算結果が埋め込まれる
  • static変数もある static STATIC_VAL: u32 = 777;
    • mutableなstatic変数も定義できる
      • 初期値はコンパイル時に確定する値にすること
      • 代入はunsafeで囲むこと (他スレッドで変更される可能性があるため)
    • static変数とは?という説明が最初にないのが不思議
  • 多くの2項演算子は異なる型同士の演算を許可してないっぽい (型強制もなしか)
  • 右シフトは符号なし型に対しては論理右シフト、符号あり型に対しては算術右シフトになるっぽい
  • if は式
    • true節とfalse節の返す値の型は同じじゃなきゃダメ
      • false節を省略した場合のfalse節の返す値は()
  • match は式
    • if同様、返す値の型は揃える
    • どのパターンにもマッチしないものはコンパイルエラー
    • 連結(or) 1|2|3
    • 範囲 4..5
    • ガード Some(s) if s.len() >= 10 => "long"
  • if let式はmatch式の糖衣構文
  • loop は式
    • loop {break ret_val;}
    • continueもある
  • while は式
    • breakやcontinueも使える
      • ただし、breakで値を返すことはできない
      • while式が返す値は常に()
  • while let式もある
    • パターンにマッチしたときは繰り返し、マッチしなかった場合はループを抜ける
    • breakやcontinueも使えるが、返す値は常に()
  • for は式
    • コレクションに対してループ
    • for elm in vector.iter() { }
    • breakやcontinueも使えるが、返す値は常に()
  • クロージャ作成時に環境の変数は「貸す」ことになるっぽい
    • 元のスコープでクロージャに貸した変数の値を変えようとするとビルドエラーになる
      • moveキーワードを使えば、値がコピーされる(Copyトレイト要)
        • let plus_one = move |x| { x + one };
  • アトリビュート コンパイラに対する指示
    • 対象アイテムの外に書く場合 #[xxx]
    • 対象アイテムの中に書く場合 #![xxx]
    • 種類はたくさんあるらしい
      • test テスト実行時(--testオプション)のみコンパイル
      • cfg(unix) 条件によってコンパイルするか決められる
      • derive(Debug) トレイとの自動実装
      • allow/deny() リントチェックを制御(allowを使えばリントチェックを無視)
  • モジュール分割 mod mod_name { fn func() {} }
    • mod_name::func()で呼び出す
    • ただし、pub付けないとアイテムは非公開となり、他モジュールから呼び出せない
    • pub(公開場所)で、細やかなアクセス制御ができるっぽい
      • pub(crate) pubを付けたアイテムと同モジュールの含むクレートに対して公開
      • pub(in app::network) app::networkモジュールに対して公開
      • crateはルートモジュール
        • crate::network::ping()
    • src/network.rsで、networkモジュールとして取り扱われる
      • ただし、モジュール使用側でmod networkという指定が必要
課題
  • static変数の命名規則は大文字区切り?
  • パターンの使い方はもっと色々見た方が良さげ
  • evcxr_replというREPLがあるっぽいけどビルドエラー
    • sig/src/ffi.rsBSDにないSIGNALを参照しているっぽい
      • SIGSTKLFT(Linux?) ... 数値演算プロセッサのスタックフォールトだとか
      • SIGPOLL(SystemV?) ... ポーリング可能イベントの発生。BSDだとSIGIO?
      • SIGPWR(SystemV?) ... 電源障害・再起動だとか。いつ使うんだろ
    • とりあえず、上を参照している行をコメントアウトしたらビルドできた
      • sigに依存した他のパッケージが上記シグナルを使ってたらアウト
      • cfgアトリビュートによって定義切り替えるのが良いのだろうか。定義統一してくれるのが嬉しいのだけれども、OS依存だもんなぁ。。。

参考

実践Rust入門[言語仕様から開発手法まで]

実践Rust入門[言語仕様から開発手法まで]