聞き流しプログラミング言語学習

PODCAST · technology

聞き流しプログラミング言語学習

生成AIが作成した汎用的なプログラミング言語の知識を、聞き流しで学習するための音声コンテンツです。個人学習用として作成しています。音声:VOICEVOX(青山龍星)

  1. 169

    Rust 030 モジュールシステム - 構造・境界・名前

    第30章へようこそ。ここまでの章では、型、所有権、参照、コレクションといった個々の仕組みを扱ってきました。これらを使ってプログラムを実際に組み立てると、コードは大きくなる。大きくなったコードを「どう配置し、何を外に見せ、どう参照するか」を決めるのが、モジュールシステムの役割です。Rustのモジュールシステムには3つの構文があります。モジュール宣言、public指定、use宣言の3つです。ソースコード上では、moduleを3文字に略してエム・オー・ディーと綴るのがモジュール宣言、publicを3文字に略してピー・ユー・ビーと綴るのがpublic指定、useをそのままユー・エス・イーと綴るのがuse宣言です。本章では、この3つの構文をそれぞれモジュール宣言、public指定、use宣言という名前で呼んでいきます。モジュール宣言は名前空間を組み立てる。public指定は何を外から見えるかを選ぶ。use宣言は別の場所の名前を短く参照するためにスコープに持ち込む。それぞれの機能は単純で、1文ずつで言い切れる。3つが別々の軸を扱うために、別々の構文として分かれている。今日扱うのは、それぞれが何をしているかと、3つを別々の軸として読むことが何を整理するか。構造の軸、境界の軸、名前の軸。この3つの分けで章を進めます。

  2. 168

    Rust 029 BTreeMap と BTreeSet - 順序を保つ対応表

    第29章へようこそ。これまでに扱ったHashMapとHashSetには、共通する性質がありました。内部はハッシュテーブルで、要素はハッシュ関数によって決まる位置に置かれる。そのため、要素は挿入順にも整列順にも並ばず、イテレーションの順序は保証されない。個々の操作はほぼ一定時間で動くが、順序にまつわる操作は構造的に難しい。順序が必要な場面があります。キーが範囲で問い合わされる場合。たとえば「ある日付以降のすべてのエントリ」「キーが10から20の間にあるもの」。イテレーション順序が一定であることが望ましい場合。出力順を整えたい、結果を予測可能にしたい。最小のキーや最大のキーを高速に取り出したい場合。これらの場面のために用意されているのがBTreeMapとBTreeSetです。役割はHashMapとHashSetと同じく、ペアの対応表と要素の集合。違うのは内部構造で、ハッシュテーブルではなくBツリーと呼ばれる木構造を使う。今日扱うのは、Bツリーがどう順序を保つか、その代償は何か、求められるトレイトはなぜ変わるか、そして範囲クエリという固有の操作です。

  3. 167

    Rust 028 HashSet と VecDeque - 派生コレクション

    第28章へようこそ。これまでの章では、Vecが連続した領域に要素を並べる構造、HashMapがハッシュ関数でキーと値を対応させる構造として扱ってきました。この2つはRustでよく使われるコレクションだが、すべての用途を覆えるわけではない。VecとHashMapには、それぞれの構造から来る向き不向きがある。Vecは連続配置のため、両端のうち末尾は高速だが、先頭への操作は重い。HashMapはペアを管理するため、あたいを持たない単純な「要素の集合」を表現するには余分な情報を持つことになる。これらの不足を埋めるために、VecとHashMapの構造を別の用途に特化させた派生形がある。今日扱うのは、HashSetとVecDeque。HashSetはHashMapを集合用に特化させたもの、VecDequeはVecを両端操作用に特化させたものです。それぞれが何を変えて、何を引き継いでいるかを構造から見ていきます。

  4. 166

    Rust 027 Entry API - 効率的な更新

    第27章へようこそ。今日のテーマはEntry APIです。前章ではHashMapの内部構造と基本操作を扱いました。キーをハッシュ関数に通して整数を得て、その整数からテーブル上の位置を決め、スロットを確認してあたいを取り出す。挿入、取得、削除、存在確認、いずれも内部ではハッシュ計算とテーブル探索を組み合わせて動きます。今日扱うのは、この基本操作だけでは無駄が出てしまう典型的な場面と、その無駄を解消するために用意された別の操作です。「キーが存在していたら既存の値を変更する。存在していなければ新しいあたいを挿入する」という処理を、HashMapに対してどう書くか。素朴に書くと、同じキーに対するハッシュ計算と探索が複数回走ってしまう。これを1回で済ませるための仕組みがEntry APIです。今日はEntry APIが解決している問題、Entryという型の構造、or_insert、or_insert_with、and_modifyの動作、そしてEntry APIが借用とどう関わっているかを扱います。

  5. 165

    Rust 026 HashMap - キーと値の対応表

    第26章へようこそ。今日のテーマはHashMapです。前章で扱ったVecは、要素が連続して並んでいる構造でした。0番、1番、2番というインデックスで要素を取り出す。インデックスがあらかじめ整数として与えられているなら、即座に要素にアクセスできる。しかし扱いたい関係が「整数で並べたもの」ではない場合があります。ユーザー名と設定情報の対応、商品コードと在庫数の対応、英単語とその訳語の対応。キーになる側が文字列や任意の型で、そのキーに対応する値を引きたい。これを実現するのがHashMapです。今日はHashMapの内部構造、ハッシュ関数の役割、衝突の扱い、キーに要求される性質、操作の動作、イテレーション順序が保証されない理由を扱います。

  6. 164

    Rust 025 Vec詳細 - 容量と成長

    第25章へようこそ。今日のテーマはVecの詳細、その中でも容量と成長です。Vecはこれまでの章でも何度か登場してきました。第20章では、Vecがスタックとヒープにまたがる型として、ヘッダ部分にポインタと長さと容量の3つを持つことを確認しました。要素を追加する基本的な動作は、第4章のイテレータの章で扱っています。今回はVec自身の動きを内側から扱います。容量とは何か、長さとどう違うのか。要素を追加するときに何が起きるのか。なぜ容量は約2倍に増えるのか。事前確保と縮小はどう動くのか。要素へのアクセスにどんな種類があるか。構造として理解すると、Vecの動きが予測可能になり、コストも見えるようになる。

  7. 163

    Rust 024 Weak - 弱い参照

    第24章へようこそ。今日のテーマは「Weakと循環参照」です。第22章で扱ったRcは、参照カウントが0になった瞬間にヒープ上のあたいを解放する型でした。誰か1人でも所有者が残っている限り、あたいは生き続ける。この設計には1つの構造的な弱点があります。複数のRcが互いに相手を所有し合うとき、カウントがどの所有者から見ても1以上のままで、永久に0に達しない状況が起こり得る。誰もアクセスできなくなった後も、ヒープ上のあたいが解放されないまま残る。これが循環参照と呼ばれる問題で、メモリリークの典型的な発生源です。この問題を解くために用意されているのがWeakです。今日はWeakの構造、強い参照と弱い参照の違い、循環をどう解くか、Rcの内部に弱カウントがどう存在しているかを扱います。

  8. 162

    Rust 023 RefCell - 内部可変性

    第23章へようこそ。今日のテーマは「RefCellと内部可変性」です。前章で扱ったRcは、複数の所有者が同じヒープ上の値を共有できる型でした。しかしRcから取り出せるのは中身への不変参照だけで、可変参照は得られない。これは「可変参照は同時に1つだけ」という借用規則と整合させるための設計でした。それでも実用上、共有している値を変更したい状況は頻繁にあります。ツリー構造で複数のノードが共通の状態を更新する。あるオブジェクトの内部キャッシュを書き換える。こういう状況のために用意されているのが、内部可変性という枠組みです。今日はRefCellを通じて、内部可変性の構造、実行時の借用検査、パニックの条件、Rcとの組み合わせを扱います。

  9. 161

    Rust 022 Rc - 共有所有権

    第22章へようこそ。今日のテーマは「Rc」です。RcはReference Countedの頭文字で、日本語にすれば参照カウントを持つ型ということ。前章で扱ったBoxは、ヒープ上のあたいに対して所有者が1人だけの型でした。ヒープを所有する型は所有者が1人というルールに従い、ムーブで所有権が移り、Copyトレイトを持たない。しかし、複数の場所から同じヒープ上のあたいを所有したい状況があります。グラフ構造で複数のノードが同じノードを指す。設定データを複数の処理が共有する。こういう構造を、所有者を1人に絞ったまま実現するのは難しい。このための型がRcです。今日はRcの内部構造、参照カウントの動き、cloneの意味、なぜ中身が読み取り専用なのか、なぜシングルスレッド専用なのかを扱います。

  10. 160

    Rust 021 Box - ヒープに置く箱

    第21章へようこそ。今日のテーマは「Box」です。前章でスタックとヒープという2つの領域を扱いました。スタックは関数呼び出しに合わせて伸び縮みし、サイズがコンパイル時に決まるあたいを置く領域。ヒープは関数の生存期間と独立に確保解放され、サイズが実行時に決まるあたいを置く領域。StringやVecはこの2つの領域にまたがる型でした。スタック側にポインタと長さと容量の3つを持ち、ヒープ側に実データを持つ。ではStringのような「特定の中身に縛られた」二層構造ではなく、任意の型をヒープに置きたいときはどうするのか。そのための型がBoxです。今日はBoxの構造、Derefによる透過アクセス、Dropによる自動解放、そしてBoxが構造として必要になる場面を扱います。

  11. 159

    Rust 020 スタックとヒープ - 2つのメモリ領域

    第20章へようこそ。今日のテーマは「スタックとヒープ」です。ここまでの章で「スタック上のポインタ」「ヒープ上のデータ」という言葉を何度か使ってきました。所有権の章ではStringの代入時にスタック上の情報が渡されると話し、文字列の章ではヒープにバイト列が置かれると話した。これらの説明は、すべてスタックとヒープという2つの領域があることを前提にしていた。今日はその2つの領域そのものを扱います。2つの領域はそれぞれどう動き、なぜ分かれているのか。そしてここまで学んだムーブやCopyトレイトが、なぜそういう形になっているのか。

  12. 158

    Rust 019 UTF-8の世界 - 文字とバイト

    第19章へようこそ。今日のテーマは「UTF-8」です。Stringも文字列スライスも、中身はUTF-8でエンコードされたバイト列でした。ここまでの章で何度か触れてきましたが、深く踏み込んでいなかった。文字列を扱うとき、「文字」と「バイト」の間にずれがあることが、さまざまな場面で現れる。長さの意味、インデックスの禁止、イテレートの方法、絵文字の扱い。これらすべての根にあるのがUTF-8の性質です。今日はその性質を見ていきます。

  13. 157

    Rust 018 文字列の変換 - 所有と借用を行き来する

    第18章へようこそ。今日のテーマは「文字列の変換」です。前の2章で、文字列が2つの型に分かれることを見ました。所有するStringと、借りる文字列スライス。2つの型がある以上、その間を行き来する必要が生じます。文字列スライスからStringを作る場面。Stringから文字列スライスを取り出す場面。この2方向の変換は、形は似ていますが中身はまったく違う。片方はヒープ割当てを伴う重い操作、もう片方は参照を組み立てるだけの軽い操作です。この非対称な関係を今日は見ていきます。

  14. 156

    Rust 017 &str入門 - 借りる文字列

    第17章へようこそ。今日のテーマは「文字列スライス」です。前章でStringを扱いました。ヒープに持つ所有権付きの可変長文字列です。文字列のもう一方の型が、今日の主役、文字列スライス。借りている文字列、参照としての文字列です。表記は&str。str単体ではほぼ使われず、参照の形でだけ現れる。所有を持たず、読み取り専用で、サイズも固定されている。Stringと対になる存在として理解します。

  15. 155

    Rust 016 String入門 - 所有する文字列

    第16章へようこそ。今日のテーマは「String」です。多くのプログラミング言語では、文字列は1つの型で扱われる。しかしRustでは、文字列を2つの型に分けている。所有する文字列と、借りている文字列。所有する方がString。借りる方が文字列スライスと呼ばれる別の型。この2つの区別は、所有権と借用の区別を文字列にも持ち込んだ結果です。今日はStringを見ていきます。ヒープに持つ所有権付きの、可変長文字列です。

  16. 154

    Rust 015 ライフタイム省略と’static - 書かなくてよい場合

    第15章へようこそ。今日のテーマは「ライフタイム省略と'static」です。前の2章でライフタイム注釈の書き方を学びました。しかし、実際のRustコードを見ると、ライフタイム注釈が書かれている関数は意外と少ない。参照を受け取って参照を返す関数でも、注釈なしで書かれていることが多い。これは、コンパイラが自動的に注釈を補っているからです。この補完の仕組みをライフタイム省略規則と呼ぶ。もう1つ、今日扱うのは'staticという特別なライフタイム。プログラムの実行中、ずっと有効であり続ける参照のライフタイムです。この2つを理解すれば、ライフタイム編の基礎が完成します。

  17. 153

    Rust 014 関数と構造体のライフタイム - 注釈を書く

    第14章へようこそ。今日のテーマは「関数と構造体のライフタイム」です。前章でライフタイムの概念を学びました。参照には有効期間があり、それが型システムの一部として扱われる。今日は、ライフタイム注釈を実際に書く場面を見ていきます。関数が参照を受け取って参照を返すとき。構造体が参照をフィールドに持つとき。メソッドを定義するとき。それぞれで注釈がどう書かれ、何を意味するかを見ていきます。

  18. 152

    Rust 013 ライフタイム - 参照の有効期間

    第13章へようこそ。今日のテーマは「ライフタイム」です。第1章で所有権と借用を学びました。値の所有者は常に1つ。参照を作ることで値を借りられる。借りている間、元の値は動かせない。しかし、第1章では触れなかった問いがあります。参照はいつまで有効なのか。参照が指している先の値が消えたら、参照はどうなるのか。この問いに答える仕組みが、ライフタイムです。ライフタイムは、参照の有効期間を型システムの一部として扱う仕組み。Rustの安全性保証の中核をなす概念です。

  19. 151

    Rust 012 関連型 - トレイトが型を持つとき

    第12章へようこそ。今日のテーマは「関連型」です。第4章でイテレータを学んだとき、Itemという言葉が出てきました。イテレータが返す要素の型。整数のイテレータなら整数。文字列のイテレータなら文字列。このItemは、Iteratorトレイトの中で定義された型です。トレイトの中に型が定義されている。これが関連型。関連型は、第10章の型パラメータと似た役割を持つように見える。どちらも「後から決まる型」を表現する。しかし、型パラメータと関連型には構造的な違いがあります。なぜRustは両方を用意したのか。どう使い分けるのか。今日はこの違いを見ていきます。

  20. 150

    Rust 011 トレイト境界 - ジェネリクスに条件を付ける

    第11章へようこそ。今日のテーマは「トレイト境界」です。前章で、制約のない型パラメータTにはほとんど何もできないと話しました。Tがどんな型かわからない以上、比較も表示も複製もできない。第8章でトレイトを学びました。トレイトは「このメソッド群を持つこと」という契約を定義する仕組みでした。トレイト境界は、この2つを結びつけます。「Tはこのトレイトを実装している」という条件を型パラメータに付ける。ジェネリクスとトレイトの合流点です。

  21. 149

    Rust 010 ジェネリクス - 型を引数にする

    第10章へようこそ。今日のテーマは「ジェネリクス」です。ここまでの章で、すでにジェネリクスに何度も出会っています。第2章のOption型。第3章のResult型。第4章のイテレータが返すVec。これらはすべて、型パラメータを持つジェネリックな型です。しかし、「型パラメータを持つ」とはどういうことか。なぜ型をパラメータにする必要があるのか。コンパイラはジェネリックなコードをどう処理するのか。今日はこの仕組みを正面から見ていきます。

  22. 148

    Rust 009 エラー処理 - エラー型を設計する

    第9章へようこそ。今日のテーマは「エラー型の設計」です。第3章でResult型を学びました。関数が失敗しうるとき、戻り値をResult型にする。Okに成功時のあたいが入り、Errにエラー情報が入る。?演算子で、エラーを呼び出し元に伝播できる。しかし、第3章では触れなかったことがあります。Errの中に入れるエラー型を、どう設計するのか。ファイルの読み込みは入出力エラーを返す。文字列のパースはパースエラーを返す。1つの関数の中で、異なる種類のエラーが発生しうるとき、戻り値のエラー型は何にするのか。エラーを受け取った側は、どうやって失敗の種類を区別するのか。第8章でトレイトを学んだことで、この問題に正面から向き合えます。Rustのエラー処理は、トレイトの仕組みの上に構築されている。

  23. 147

    Rust 008 トレイト - 型と振る舞いを分離する

    第8章へようこそ。今日のテーマは「トレイト」です。第6章で構造体とenumを扱いました。構造体はデータの形を定義し、implブロックでメソッドを付けた。しかし、あのメソッドは特定の構造体にしか使えない。構造体Aに定義したメソッドは、構造体Bには使えない。ここで疑問が生まれます。異なる型が同じ操作を持つことを、どう表現するのか。たとえば、文字列として表示するという操作は、整数にも浮動小数点数にも構造体にも欲しい。しかし、それぞれの型で表示のやり方は違う。整数なら数字の列に変換する。浮動小数点数なら小数点を含む形に変換する。構造体ならフィールドを順に並べる。操作の名前は同じだが、実装は型ごとに違う。この「共通の操作名」と「型ごとの実装」を分離する仕組みが、トレイトです。トレイトはRustの型システムの中核にある概念です。今日はトレイトが何を解決し、どう機能するかを、構造から見ていきます。

  24. 146

    Rust 007 パターンマッチ - 値の構造で分岐する

    第7章へようこそ。今日のテーマはパターンマッチです。第2章のOptionでmatchを使ってSomeとNoneに分岐しました。第3章のResultでもmatchでOkとErrに分岐しました。第6章のenumでも、バリアントの判定にmatchを使うと説明しました。これまで道具として使ってきたmatchの背後には、「パターン」という仕組みがあります。パターンとは、あたいの構造を記述する式です。matchは値とパターンを照合し、一致したパターンに対応する処理を実行する。今日はこのパターンという仕組みを体系的に扱います。パターンが使える場所はmatch式だけではない。let束縛、関数の引数、forループにもパターンが現れる。パターンはRustの構文全体に組み込まれた仕組みです。

  25. 145

    Rust 006 StructとEnum - データに形を与える

    第6章へようこそ。今日のテーマはstructとenum、つまり構造体と列挙型、です。ここまでの章で、i32やString、boolといった型を使ってきました。これらはRustが最初から用意している型です。しかし実際のプログラムでは、これだけでは足りない。ユーザーの名前と年齢とメールアドレスを1つにまとめて扱いたい。処理の結果が「成功」「タイムアウト」「認証失敗」のどれかであることを型で表したい。structとenumは、プログラマが自分で型を定義するための仕組みです。structは「これらのデータをすべて持つ」型を作る。enumは「これらの可能性のうちどれか1つ」を表す型を作る。この「すべて」と「どれか1つ」の区別が、今日の章の核心です。

  26. 144

    Rust 005 クロージャ - 環境を捕獲する関数

    第5章へようこそ。今日のテーマは「クロージャ」です。第4章のイテレータで、mapやfilterに小さな関数を渡しました。あの小さな関数の正体がクロージャです。クロージャと普通の関数の違いは1つです。クロージャは、自分が定義された場所の周囲にある変数を捕まえて、自分の中で使える。関数にはこれができない。この「周囲の変数を捕まえる」という一点が、クロージャの性質のすべてを決めます。捕獲は所有権の仕組みと直接噛み合うため、Rustのクロージャは型の表現が細かく分かれている。今日はその内部構造まで踏み込みます。

  27. 143

    Rust 004 イテレータ - 流れとして処理する

    第4章へようこそ。今日のテーマは「イテレータ」です。複数の要素を順番に処理する。これはあらゆるプログラムで現れる基本的な操作です。配列の要素を1つずつ見る。リストを変換する。条件に合うものだけを集める。Rustでは、こういった処理をイテレータで書く。イテレータは、データを「流れ」として扱う仕組みです。map、filter、collectといったメソッドをドットで繋いで、流れに対する処理を連鎖させる。書き慣れていれば簡潔で美しい。しかし初めて見ると、ドットで繋がった先で何が起きているのか、データがどの順番でどこを通るのか、理解するのが難しい。今日の章では、この「ドット連鎖の中で何が起きているか」を中心に見ていきます。

  28. 142

    Rust 003 Result - 失敗を型で表現する

    第3章へようこそ。今日のテーマは「Result型」です。第2章で、の不在をOption型で表現することを学びました。 Nullの代わりに、不在を型として明示する仕組み。Result型はOptionと似た構造を持つが、表現するものが違う。Optionは「あるかないか」。Resultは「成功したか失敗したか、そして失敗ならその理由」。ファイルの読み込み、ネットワーク通信、文字列のパース。これらは失敗する可能性のある処理です。Rustでは、こういう関数の戻り値はResult型になる。

  29. 141

    Rust 002 Option - 値の不在を型で表現する

    第2章へようこそ。今日のテーマは「Option型」です。多くの言語には、nullがある。値が存在しないことを表す特別な印。しかしnullは、プログラミングの歴史において最も多くのバグを生み出してきた概念の一つ。nullを発明した本人が「10億ドルの間違い」と呼んでいる。Rustにはnullがない。代わりに、値が存在しないかもしれないことを型で表現する。それがOption型です。

  30. 140

    Rust 001 所有権 - Rustの心臓部

    第1章へようこそ。今日のテーマは「所有権」です。Rustにおいて、すべてのデータには所有者がいる。所有者は常に1人。この規則が、Rustの根幹を支えている。所有権はメモリ管理の仕組みであり、型の設計に影響し、関数の引数の渡し方を決める。この先の章で学ぶ借用、ライフタイム、ムーブ、クローン。これらはすべて、所有権から派生した概念です。まず所有権とは何か、なぜ存在するのかを見ていきます。

  31. 139

    Rust 140 メモリの統合 - すべてはメモリに帰る

    第140章へようこそ。第139章で、asyncタスクの境界において、所有権、型、ライフタイム、Sendが同時に問われることを見ました。別々の制約ではなく、メモリの安全を守る1つの構造の異なる面であると。今日のテーマは「メモリの統合」です。第126章からここまで、メモリの姿を追ってきました。バイト列。アドレス。スタック。ヒープ。アライメント。パディング。判別子。vtable。ファットポインタ。ステートマシン。これらはすべて、メモリの中の具体的な構造でした。そして、所有権。借用。ライフタイム。型。トレイト。Send。Sync。これらはすべて、その構造に対する規則でした。今日は、個別の概念には踏み込みません。代わりに、すべての次元を貫く1つの問いを浮かび上がらせます。

  32. 138

    Rust 139 メモリ境界 - asyncと所有権が交差するとき

    第139章へようこそ。第138章で、async関数がenumに変換されることを見ました。中断のたびに判別子とデータが書き換わり、再開のたびに読み出される。Futureの状態はヒープ上のenumに保持される。今日のテーマは「メモリ境界」です。そのenumの中に何を入れられるか、という問いに向き合います。async関数の中で使う変数は、awaitをまたげばenumのフィールドになる。しかし、すべての値がenumに入れるわけではない。タスクの境界を越える値には条件がある。その条件は、第134章で学んだSendとSyncに直結している。並行性の次元と時間の次元が、ここで交差します。

  33. 137

    Rust 138 asyncの内部構造 - ステートマシンがメモリに刻まれるとき

    第138章へようこそ。第137章で、vtableの構造を見ました。トレイトオブジェクトが型を消去しても、vtableのメタデータが正しい解放を保証する。今日のテーマは「メモリ状態機械」です。asyncの内部構造を見ます。第49章でasync/awaitを学びました。第50章でFutureトレイトを学びました。async関数はステートマシンに変換される。各awaitが状態の境界になる。あのとき、ステートマシンの姿は抽象的に語りました。今日は、メモリの側から見ます。async関数がコンパイルされたとき、メモリの中には何があるのか。中断した瞬間、変数はどこに保持されているのか。再開した瞬間、CPUは何を読んでいるのか。asyncの内部構造を、バイトの粒度で見ていきます。

  34. 136

    Rust 137 メモリ上の仮想表 - ブイテーブルの構造

    第137章へようこそ。第136章で、enumとメモリの関係を見ました。判別子がバリアントを識別し、ニッチ最適化がビットパターンの隙間を活用する。型のメモリ表現が、コンパイラの知識によって最適化される姿でした。今日のテーマは「メモリ上の仮想表」です。vtableの構造を見ます。第129章で、トレイトオブジェクトのファットポインタを学びました。データへのポインタとvtableへのポインタ。合計16バイト。vtableとは仮想メソッドテーブルであると語りました。しかし、vtableの中身は見ていません。vtableはメモリ上でどのような形をしているのか。何が記録されていて、どうやって使われるのか。なぜこの構造が必要なのか。動的ディスパッチの心臓部を、バイトの粒度で見ていきます。

  35. 135

    Rust 136 メモリと判別子 - enumの内部表現

    第136章へようこそ。第135章で、ジェネリクスとメモリの関係を見ました。型パラメータが具体化されるとき、メモリレイアウトが確定する。モノモーフィゼーションとは、メモリレイアウトの生成規則が具体的な形をとることでした。今日のテーマは「メモリと判別子」です。enumの内部表現を掘り下げます。第127章で、enumはタグとデータの組み合わせだと語りました。タグが今どのバリアントかを表し、データがそのバリアントの値を保持する。Optionで参照を包んだとき、タグが省略される最適化があることにも触れました。今日は、その先に進みます。タグはメモリ上でどのような姿をしているのか。コンパイラはタグのサイズをどう決めているのか。タグを省略できる条件とは何か。そして、Optionの最適化は参照だけの話なのか。enumの内部表現を、バイトの粒度で見ていきます。

  36. 134

    コンピュータ基礎 031 メモリオーダリング - 書いた順に実行されるとは限らない

    前章まで、データ競合と同期の仕組みを見てきました。複数のコアが同じアドレスに同時にアクセスすると、データが壊れる。アトミック命令やミューテックスで保護する。今日は、もう1つの問題を見ます。プログラムに書いた命令の順序と、実際に実行される順序が異なる。この問題を「メモリオーダリング」と呼びます。メモリへの読み書きが、どの順序で観測されるかという問題です。

  37. 133

    Rust 135 メモリ具体化 - ジェネリクスが形を持つ瞬間

    第135章へようこそ。第134章で、並行性とメモリの関係を見ました。複数のスレッドが同じバイト列に触れるとき、型システムが安全を構造的に保証する。今日のテーマは「メモリ具体化」です。ジェネリクスが形を持つ瞬間を見ます。第7章でジェネリクスを学びました。第120章で、ジェネリクスのゼロコスト抽象を語りました。モノモーフィゼーション。コンパイル時に具体的な型で展開される。今日の問いは、ジェネリクスがメモリにどう影響するか。ジェネリックな関数を書いたとき、メモリの中には何があるのか。型パラメータが具体化されるとき、メモリレイアウトはどう決まるのか。ジェネリクスとトレイトオブジェクトで、メモリの姿はどう異なるのか。抽象が具体になる瞬間を、メモリの側から見ます。

  38. 132

    コンピュータ基礎 030 同期 - データを守る仕組みとその代償

    前章で、データ競合の物理的な原因を見ました。読み出しと書き戻しの間に隙間がある。キャッシュコヒーレンシはこの隙間を保護できない。今日は、この問題に対処する仕組みを見ます。ハードウェアが提供するもの。その上にソフトウェアが構築するもの。そして、対処の代償。

  39. 131

    Rust 134 メモリと並行性 - 複数のスレッドが同じバイト列に触れるとき

    第134章へようこそ。第133章で、借用チェッカーをメモリの視点で再訪しました。不変参照の共有、可変参照の排他性、ライフタイムの検証。すべてがメモリのバイト列を正しく読み書きするための規則でした。しかし、第133章の議論には暗黙の前提がありました。実行の流れが1つであるという前提です。今日のテーマは「メモリと並行性」です。実行の流れが複数ある場面を見ます。第42章でSendとSyncを学びました。第43章でMutexを学びました。第128章でArcのメモリ構造を見ました。これらを、メモリの姿が見える目で読み直します。1つのスレッドが1つのメモリ領域を読み書きしているとき、借用チェッカーが安全を保証する。複数のスレッドが同じメモリ領域に触れようとするとき、何が起きるのか。そして何がそれを防ぐのか。

  40. 130

    コンピュータ基礎 029 データ競合 - なぜデータが壊れるのか

    前章の最後で、同じメモリアドレスのデータが異なるコアのキャッシュに別々のコピーとして存在しうることを確認しました。今日は、この構造の上で何が起きるかを見ます。なぜデータが壊れるのか。物理的な原因を追います。

  41. 129

    Rust 133 メモリアクセス規則 - 借用チェッカーの本質

    第133章へようこそ。第132章まで、メモリの姿を見てきました。型がバイト列になる姿。所有する型と借りる型のメモリ構造。ムーブと複製の実体。メモリの一生。アロケータの仕組み。今日のテーマは「メモリアクセス規則」です。メモリの物理的な姿が見えるようになった今、借用チェッカーを再訪します。第1章で借用を学びました。第107章で借用チェッカーの詳細を学びました。第126章で借用を「メモリへのアクセス制御」と位置づけました。今日は、借用チェッカーの規則を、メモリの姿が見える目で読み直します。規則の意味が変わるはずです。抽象的なルールではなく、メモリの中で何を防いでいるかが見える。

  42. 128

    コンピュータ基礎 028 スレッド - 1つのプロセスの中の複数の実行の流れ

    前章で、並行処理と並列処理を学びました。1つのコアがコンテキストスイッチで複数のプロセスを交互に実行する。複数のコアがあれば、複数のプロセスが物理的に同時に動く。ここまで、複数の処理はすべて「複数のプロセス」でした。第18章で学んだ通り、プロセスは別々のプログラムです。ブラウザとテキストエディタ。それぞれが独立したメモリ空間を持つ。今日は、1つのプロセスの中に複数の実行の流れを持つ仕組みを見ます。

  43. 127

    Rust 132 メモリ配分 - アロケータの仕組み

    第132章へようこそ。第131章で、メモリの一生を追いました。スタック上の値は、スコープを抜けるときにスタックポインタの巻き戻しで消える。ヒープ上のあたいは、スコープを抜けるときにDropを通じてアロケータに返される。ヒープの確保と解放のとき、「アロケータ」という言葉が登場しました。今日のテーマは「メモリ配分」です。アロケータの仕組みを見ます。Vecに要素を追加するとき、ヒープ上にメモリが確保される。Stringが成長するとき、より大きなヒープ領域が確保される。Boxを作るとき、ヒープに値の分のメモリが確保される。この「確保」を行っているのが、アロケータです。アロケータとは何か。何をしているのか。なぜその存在を知る必要があるのか。

  44. 126

    コンピュータ基礎 027 並行と並列 - 複数の処理が動くとは何か

    第22章から第26章まで、IOを具体的に見てきました。マウスが動いたとき、CPUは割り込みが来るまで別の仕事をしていた。ディスクにデータを要求したとき、プロセスは待機中になり、CPUは別のプロセスを動かしていた。「別の仕事をしていた」「別のプロセスを動かしていた」この言葉を何度も使ってきました。しかし、複数の処理が同時に動くとはどういうことなのか。まだ正面から見ていません。今日はこの問いに答えます。

  45. 125

    Rust 131 メモリの一生 - 確保、使用、解放

    第131章へようこそ。第130章まで、メモリの姿を見てきました。第127章で、型がバイト列になる姿。第128章で、所有する型がスタックとヒープにまたがる姿。第129章で、借りる型がポインタとして存在する姿。第130章で、あたいが移動するときのバイト列の複製。これらはメモリの構造と動きの話でした。今日のテーマは「メモリの一生」です。メモリの時間の話をします。値が生まれるとき、メモリが確保される。値が使われているあいだ、メモリが占有される。値が消えるとき、メモリが解放される。この一生を、メモリの視点で追います。

  46. 124

    コンピュータ基礎 026 ルーティング - データが宛先に届くまで

    前章で、データが自分のコンピュータから送り出されるまでを見ました。プロセスのデータにヘッダが層ごとに付き、フレームとして組み立てられ、NICが差動信号に変換してケーブルに送り出した。データはコンピュータの外に出た。ケーブルの先にある機器から、次の機器へ。データはどうやって目的地にたどり着くのか。

  47. 123

    Rust 130 メモリの移動 - ムーブとコピーの正体

    第130章へようこそ。第128章で、所有する型のメモリ構造を見ました。第129章で、借りる型のメモリ構造を見ました。今日のテーマは「メモリの移動」です。ムーブとコピーの正体を見ます。第1章で所有権を学んだとき、ムーブを学びました。値の所有権が別の変数に移る。元の変数はもう使えない。第2章でCopyトレイトを学びました。ムーブの代わりに複製が行われる型。元の変数も引き続き使える。これらの動作は、メモリの中で何をしているのか。ムーブとは、メモリのレベルで見ると何が起きているのか。Copyトレイトの複製とは、ムーブと何が違うのか。Cloneトレイトとは、何をしているのか。今日はこれを見ていきます。

  48. 122

    コンピュータ基礎 025 ネットワーク - データが線に乗るまで

    マウスでは、デバイスからCPUへデータが届く流れを見ました。ディスクでは、プロセスの要求がディスクに届き、データが戻る流れを見ました。どちらもコンピュータの内部、あるいはすぐ隣の話でした。今日は、データがコンピュータの外に出る話です。あるコンピュータから別のコンピュータへ、データを送る。当たり前のように使っているが、その裏で何が起きているのか。今日は、データが自分のコンピュータから送り出されるまでを追いかけます。

  49. 121

    Rust 129 メモリ上の参照 - 借りるとはポインタを持つこと

    第129章へようこそ。第128章で、所有する型のメモリ構造を見ました。Vec、String、Box、Rc。スタック上のヘッダがヒープ上のデータを指す。所有者がデータの生死を握る。今日のテーマは「メモリ上の参照」です。所有しない側を見ます。参照。スライス。第1章で借用を学びました。値を所有せずに、一時的にアクセスする仕組み。第126章で、借用を「メモリへのアクセス許可」と見直しました。この「アクセス許可」は、メモリの中でどんな姿をしているのか。

  50. 120

    コンピュータ基礎 024 ディスク - 読み込み要求が届くまで

    前章で、マウスの動きを追いかけました。物理的な動作がセンサーで検出され、USBバスを通り、割り込みでCPUに届き、OSがプロセスにイベントを届ける。外の世界から内側への流れでした。今日は、逆方向を追いかけます。プログラムが「ファイルを読みたい」と要求する。この要求が、ソフトウェアの層を下り、ハードウェアに届き、物理的な動作が起き、データが逆の道を戻ってくる。内側から外へ、そして外から内へ。往復です。

Type above to search every episode's transcript for a word or phrase. Matches are scoped to this podcast.

Searching…

We're indexing this podcast's transcripts for the first time — this can take a minute or two. We'll show results as soon as they're ready.

No matches for "" in this podcast's transcripts.

Showing of matches

No topics indexed yet for this podcast.

Loading reviews...

ABOUT THIS SHOW

生成AIが作成した汎用的なプログラミング言語の知識を、聞き流しで学習するための音声コンテンツです。個人学習用として作成しています。音声:VOICEVOX(青山龍星)

HOSTED BY

ますたーさん

CATEGORIES

URL copied to clipboard!