3/5 モダンな言語は歴史的経緯がなくて良い

6時起床。4時に起きたけど「起きるの嫌だなあ」と思ったら二度寝してた。なんか中学受験してた夢見た、問一が難しすぎて時間の8割使ったけど、それ以降の問題見たら明らかに簡単で全体見てから時間配分決める奴だったーと思ったら起きた。なんの夢だよ。

 

本が大量に届いた。Amazonで10冊以上注文すると10%ポイントが付く。本屋じゃ有り得ないサービス。ポイント上限が1500ポイントなので10冊で15000円くらいが理想。なのでさっさと読める新書が多い。小説でもいいんだけど積読になりやすい上に既に積読がちょいちょいあるから新書にした。

f:id:polygonal_line:20230305210823j:image

RUSTの本が届いたので、早速取り掛かる。以下学習メモ。俺による俺のためのなので読んでいる人にはマジで意味ない。でも日記ってそもそもそういうもんだから。

 

基礎から学ぶ 組込みRust

基礎から学ぶ 組込みRust

Amazon

RUST学習メモ

  • println!()ってlnはlineなのは分かるけど、!ってなんなんだよと思ったらマクロの意味らしい。そもそも関数じゃなかった。たしかにpanic!()とか!ついてたから納得。
  • 変数のletって何の略称なのと思ったら、調べたら単なる英単語の「let」みたい。JS由来っぽい。個人的にはautoのほうが型推論強いんだからピッタリじゃないと思うけど、まあ慣れるか。
  • const,staticは変わらないみたい。C/C++みたいに修飾子の位置で意味合いが変わらないことを祈る。
  • データ型にint型がないのが良い。処理系でintのサイズは16ビットと32ビットで変わるから、ものすごくたまに問題になる。この前後輩がintを32ビットと思っていたら、実は16ビットで値がオーバーフローしていて意図しない挙動をしていたなんてことあった。そんなことはないほうが良いに決まっているし、そもそもintの次がlongだし、longより大きい型がlong longってバカみたいだよな。その点、RUSTはi8,i16,i32,i64と分かりやすくて短いので良い。
  • 整数リテラルは任意の場所に‗を入れられる。0x1357_9753、0b0000_1010_0011_1111とか。レジスタみやすくなるかも。
  • bool型はbool型、TRUE=1だったりしない。
  • 文字列リテラルの先頭にbをつけるとバイト配列として扱える。
  • if文は条件式に()をつけない。個人的には()を付けたほうが慣れ親しんでいるので、付けたらワーニングで不要な括弧を外せと怒られた。
    #[allow(unused_parens)]
    を付けたらワーニングが出なくなった。RUSTの流儀に従うほうが正しいのは分かるんだけど、C/C++を書くときに混同しちゃうと面倒なので統一できるところは統一したい。
  • true/falseの条件式しか書けないので、x == 1 の代わりに、 x = 1と書いてもコンパイルエラーで怒られる。
  • for文はイテレータで繰り返し処理するので、範囲外参照しない
  • RUSTでは関数内の最後の式が戻り値となる。式なのでセミコロンはつけない。セミコロンをつけると文になるのでreturnが必要。そういえばreturn文っていうもんな。RUSTではreturnを用いないスタイルが好まれる。明示的にreturnを用いるのは早期リターンしたいときなど。
  • structは、struct 構造体名{フィールド名:フィールド型,...}で定義。アクセスにはドットで呼び出し。「構造体名.フィールド名」
  • impl(implementation:実装)で構造体のメソッドと関連関数を定義できる。impl 構造体名{fn 関数名(引数, ...)->戻り値型{関数本体} ...} という形式
  • メソッドは、構造体に紐づく関数。なので、第一引数に構造体オブジェクト(self)が必要。
  • 関連関数は、引数にselfを受け取らない関数。オブジェクトを生成するコンストラクタとしてよく使われるらしい。デフォルト値で生成したいとき、いちいちパラメータ打つの面倒だから、コンストラクタにしちゃう感じ?
  • RUSTの列挙型は、C/C++の列挙型と違いパワフル。各ヴァリアントが異なるデータ型を持つことができる、match文で便利。列挙型にもimplでメソッドと関連関数を定義可能。列挙型にメソッドが必要なのか?と思うけど役立つんだろうきっとなにかに。
  • Option型は、値が格納されているかどうかが不明なことを表現する型。値が格納されていればSome(T)、されていないとNoneがかえってくる。Option型の値は、中身の値を扱うときにOption型から取り出す、広げる(unwrap)必要がある。具体的にはunwrap()メソッドを用いるのが手軽。
  • unwrap関数は正常な場合はその値を返し、エラーだった場合はプログラムを強制終了する(panic!)という関数。強制終了させるのがいいのかは疑問なので、unwrap の類似メソッドで panic の代わりに任意のデフォルト値を指定することができる unwrap_or と panic の代わりにクロージャを実行した値を返す unwrap_or_else があるらしい。詳しくは以下。ちゃんとエラーハンドリングしたいときに読む。

    qiita.com 

  • Result型は、値かエラーかどちらかが格納されていることを表現する型。Option型と同様。なんでこんなことをするのかというと、Rustが例外もnullも持たないから。null値からメソッド呼び出しを行って意図しないNullPointerExceptionが発生したり、例外のcatchが漏れてプログラムが落ちてしまったりしないように、Rustはこのような不具合をコンパイル時に防止するため、Result型やOption型を用意してエラーハンドリングを強制している、とのこと。(以下より引用)

    qiita.com

    ありがたい話ですね。エラーも言わずに無言で死ぬのが一番怖いし面倒。
  • 所有権システムが解決したい課題の1つは、メモリの安全性をコンパイル時に確保すること。これによりダングリングポインタを作らずに済む。また、メモリ解放忘れがなくなりメモリリークがなくなる。
  •  所有権システムは、所有権、借用、ライフタイムの3つで成り立っている。
  •  所有権は、値にアクセスする権利。借用は、所有権を一時的に貸し出して参照を作る仕組み。ライフタイムは、所有権を貸し出す期間。
  •  所有権は、コピーするかムーブするかで振る舞いが変わる。Copyトレイトを実装している整数型、bool型、浮動小数点型は値をコピーするため、所有権は移動しない。所有権と値をコピーするイメージ。コピーされた側は継続して使用可能。コピーコストが低いものはCopyトレイトを実装する。値のコピーコストが高いものは、値をコピーせずに所有権をムーブしている。ムーブされた側は継続して使用できない。
  • 借用は、関数に所有権をムーブさせるときにいちいち明示的に渡して返してもらうのは面倒なので、引数に&をつけて参照する。スマートポインタすね。可変参照のときは&mut。
  • ライフタイムは、値の所有者が貸した参照より長く生存することを保証する仕組み。参照の有効な期間をチェックする機能をボロ―チェッカーという。
  • ライフタイムパラメータがいまいち必要性が分からないけど、コンパイラがライフタイムわからなくなるときがあるから明示的に書いてあげるときに必要なんすかね
  • ジェネリクスとトレイトは、RUSTでポリモーフィズムを実現する手段。
  • ジェネリクスは、具体的なデータ型に直接依存しない、抽象的なプログラムを記述するための方法。テンプレート(T)すね。
  • トレイトは、異なる構造体同士が持つ共通の機能を定義する。抽象基底クラスすね。
  • 型変換は厳しめ。Into,Fromトレイトで変換できるけど、TryInto,TryFromトレイトは明示的にインポートしないとだし、戻り値はresult型だからエラーハンドリング考えないとだし。安全だけど面倒だね。どうにか楽にやる方法を検討しないと。
  • パッケージ=ソリューション、クレート=プロジェクトor外部ライブラリ、モジュール=ソース、ヘッダーファイル
  • Cargo.tomlはパッケージのメタ情報が記述されている
  • は、OSを用いる機能(ファイルシステム、スレッド)などを提供するstdクレートを使用しないという宣言。stdクレートのほかに、プラットフォームに依存しない基本機能のcoreクレート、ヒープメモリを使用するallocクレートがある
  • #![no_main]は、Rust標準のmain()関数インターフェースを使用しないことをコンパイラに指示する。Rust標準だとmain()関数の前処理にstdクレートを使用するため、組込み向けには#![no_main]を入れておく。
  • パニックハンドラはstdクレートで定義されているので、#![no_std]を用いるとパニックハンドラが未定義となる。そのため、パニックハンドラのクレートを用いて定義する必要がある。色々種類があるみたい。
  • #[entry]アトリビュートを関数前につけることで、アプリケーションのエントリーポイントであることを示す。
  • 関数の戻り値が!となっている関数は、発散する関数であり、その関数から戻らないことを意味する。#[entry]アトリビュートを付与する関数では戻ることのないようにする。組込みだからね。

チャプター5まで読み終わって、Wio-TerminalでLチカ完了。

 

キリが良いし、委員長のホグワーツ配信が始まったので配信観ながらホグワーツやる。インペリオ(服従呪文)を覚えた。便利そうだけど普通に火力高い魔法ぶつけたほうが早いな。

ホグワーツの世界というか主人公が割とヤバいやつだけど他のキャラもたまに???ってなることがあるので、主人公がヤバいのかそれとも魔法使いの世界がヤバいのか分からん。