Skip to content

Latest commit

 

History

History
360 lines (313 loc) · 29.1 KB

20210509101246-programming_language.org

File metadata and controls

360 lines (313 loc) · 29.1 KB

Programming Language

概要

プログラミング言語は、コンピュータへの命令を記述する言語。

Memo

DWARF(Debugging With Attributed Record Formats)

DWARFは、デバッグ情報の形式の1つ。主にC、C++、およびその他のプログラミング言語のコンパイル済みバイナリに埋め込まれるデバッグ情報を記述するために使用される。DWARFは、ソースコードとバイナリコードの間の対応関係を確立し、デバッグ時にソースレベルの情報を提供するために設計されている。

DWARFフォーマットは、変数の位置(Location)情報を表現するために使用される。これによってデバッガが変数の値を追跡したり、ブレークポイントを設定できる。また、ステップ実行したりする際に、変数のスコープや値を正確に把握できる。

DWARF locationは、変数の値がどこに格納されているかを示す情報。変数がレジスタ内にある場合は、レジスタ番号やオフセットを指定する。変数がメモリに格納されている場合は、メモリアドレスやオフセットを指定する。デバッガは、DWARF location情報を解釈して、変数の現在の値を特定できる。

DWARF location情報は、スタックフレームやグローバル変数、静的変数など、プログラム内のさまざまな場所で使用される。デバッグ情報の一部として、DWARF location情報はバイナリに埋め込まれ、デバッグ時に使用される。

式(expression)と文(statement)

よく、わからなくなる。

  • プログラミングにおける式と文とは - 愚鈍人
    • 式は文の構成要素。 例えば、if文の中の判定条件は式
      • 条件判定の式の中でも、セミコロンを使って文にして代入とかできる
    • 文と式の最大の違いは、値を返すのが式で、返さないのが文
      • 多くの言語でifで始まる構文は値を返さず、代入できないので文
      • 関数定義は文
      • クラス定義は文
      • 代入は文
      • 代入の右辺は値を返しているので式
      • returnの引数は値を返しているので式
      • if 条件 本体 の全体は文。条件は式。本体は文。

データ型uint8

uint8は8ビット(1バイト)の符号なし整数のデータ型。つまり2の8乗で0~255の値が入る。例えば、JavaScriptではバイナリを表示したときのuint8の配列で [1, 2, 3, 2, 5 ...] というように返ってくる。uint8の配列によってバイナリを表現できる。

セマフォとは排他制御の仕組みのこと

排他制御の仕組みのこと。同時に使える人の数が決まっているものに割り当てられた「あと何人の人が使えるよ」を表した数字。

最大接続数が3だとして、セマフォの中で実行を開始するとカウントが2になる。0になると実行開始をやめ、新規実行しなくなる。先に実行していたスレッドが終了するとカウントが1になり、再度実行開始されるようになる。

セマフォを使ってプログラム間の足並みを揃えることもできる。ある共通リソースにアクセスする部分でだけ同期して、ほかの関係ない部分は並列することによって、資源を効率的に活用できる。

式(expression)と文(statement)の違い

式は値を生成し、文はしない。

  • 5 は値5を生成するので式
  • let a = 1 は値を生成しないので文

値を生成するかどうかはプログラミング言語によって変わる。なので言語によってはif式、if文となる。

まずインターフェースを決めてから実装する

設計のいい話。

シングルスレッドサーバをマルチスレッド化する - The Rust Programming Language 日本語版

コードの設計を試みる際、 クライアントのインターフェイスをまず書くことは、設計を導く手助けになることがあります。呼び出したいように構成されるよう、 コードのAPIを記述してください; そして、機能を実装してから公開APIの設計をするのではなく、その構造内で機能を実装してください。

背景を理解する重要性

問題解決するだけでは応用性という点で十分でない。やっていることを完全理解するために調べたり書く。次の似たような問題が対応できるようになる。毎回ちょっと違うことをググることになるなら、理解できてない。

言語の学びやすさと分野

言語そのものより、その分野に既存のプロジェクトがどれくらいあるか、も大きい。難しくても、参考になるコードが簡単に見つけられれば学習は容易になる。また、使い慣れたソフトがあるなら最高だ。何をするのかあらかじめわかっていれば理解しやすい。

  • 121,134,152,168,185, 235
  • コードをどう組み合わせるか。アーキテクチャに関する本
  • 構造化、関数型、オブジェクト指向…プログラミングパラダイムは、どれも制限を課すものである
  • オブジェクト指向のもっとも有益な特徴はポリモーフィズムである。ソースコードの依存関係を実行順序と関係なくできる。ビジネスロジックが最上位にあり、下位にライブラリやデータベースを置き、これらは交換可能である。実行順序とは逆だ
  • プラグインアーキテクチャは、上位レベルの方針を含んだモジュールを下位レベルの詳細を含んだモジュールから独立させること。下位レベルの詳細はプラグインモジュールとなり、上位レベルの方針を含んだモジュールとは独立して、デプロイおよび開発することが可能となる
  • 単一責任原則(SRP)の失敗例: Employeeクラスに、経理、人事部門、データベース管理者の3つの部門の責務が入っているようなとき。
    • つまり、アクターの異なるコードは分割すべきということ
  • オープン・クローズドの原則(OCP): ソフトウェアの振る舞いは、既存の成果物を変更せず拡張できるようにすべきである。
    • ローグライクチュートリアルがまさにそんな感じだった。機能追加で既存の箇所をいじる必要はなく、独立している
    • ちょっとした拡張のために大量の書き換えが必要になるようなら、そのソフトウェアシステムのアーキテクトは大失敗への道を突き進んでいる
  • 依存性逆転の法則: ソースコードは具象に依存するべきではない。変化しやすい具象クラスを参照しない、継承しない。重要な部分が、重要でない部分に依存しないように設計すべき
  • 再利用・リリース等価の原則: 同じタイミングで変更されることが多いクラスはひとつにまとめる
  • 閉鎖性共通の原則: 同じ理由、同じタイミングで変更されるクラスをコンポーネントにまとめること。変更の理由やタイミングが異なるクラスは、別のコンポーネントに分けること
  • 全再利用の原則: コンポーネントのユーザに対して、実際には使わないものへの依存を強要してはいけない
  • 安定依存の原則: 安定度の高い方向に依存する
  • 安定度・抽象度等価の原則: コンポーネントの抽象度は、その安定度と同程度でなければならない。安定度の高いコンポーネントは抽象度も高くあるべき
  • 優れたアーキテクトは、方針と詳細を慎重に区別して、方針が詳細を把握することなく、決して依存することがないように、両者を切り離す
  • アーキテクチャがサポートしなければいけないこと:
    • システムのユースケース
    • システムの運用
    • システムの開発
    • システムのデプロイ
  • 注文入力システムに注文を追加するユースケースは、注文を削除するユースケースと比べると、明らかに異なる頻度と理由で変更される
  • 優れたアーキテクトは、システムの詳細の決定を従属的かつ遅延可能なものにする

Tasks

作り方の解説本。

ゲームプログラマのおすすめ本。

プログラミング言語を作る本。

検索システムの本。

テキストエディタを作る。

信頼への反省。ケン・トンプソンの論文。

言語設計者へのインタビュー集。

2つの型の違いは何か。

インタプリタを実装する。

設計。 コードが書けるレベルに具体化するまで行う。 設計をレビューしてくれる人がいない場合は一週間放置して見返してみる。 自分の設計を理解するのが難しく感じたのなら、自分以外の人が理解するのはもっと難しい。 トップダウン、ボトムアップを併用する。 トップダウンは最初簡単だが、あとの複雑さに気づかないことがある。 ボトムアップは最初難しいが、複雑さを早い段階で明らかにできる可能性がある。 最初に思いついた設計は間違っている。

クラス。 クラスがどのような抽象化を実装しているのか理解する。 できるだけ実装を隠し単純化する。

実装パターンの解説書。

References

読み方、書き方。

キャッチアップする意義や方法。

セマンティクスとシンタックスの違いの説明。

同じプログラムの新しいバージョンを作ること。

おすすめのリンク集。

役に立つ記事リスト。

謎に包まれたコントリビュートのプロセスの、ヒント。

それに、過去には「Rust Compiler Ambitions for 2022」というブログ記事の「What do I do if I’m interested in compiler development but have no experience in compilers?」という項目の中で「コンパイラ開発の経験がなくても気にしなくていい」「今コントリビューションしているメンバーも、Rustの開発をしながら徐々にコンパイラの知識を身につけたんだ」という旨のことが書かれています。

自分のスキルの高低は気にせず、できることから手をつけたらいいと思います。コミッターたちに質問できる場も用意されているので、困ったことがあれば誰かしら助けてくれるはずです。

小さいことから始める。

メタオブジェクトプロトコルのバイブル。

DSLの本。 よくあるテクニックがどういう仕組みで動いているか解説。

オブジェクト指向に対する、理解しやすいが間違った説明の議論。

役立つリンク集。

大きなシステムの設計方法を学ぶ方法。

シンプルなデザインパターンの解説。

プログラマーが知るべきこと。

エッセイの日本語訳。

モナドの解説。

pryデバッグの方法。

あらゆるプログラミング言語のhello world集。

データ指向のデザイン。

エンジニアリングに関する面白い記事がある。

オブジェクト指向の原則。

ゲームプログラミングでよく使われるデザインパターン。

Archives

優れたプログラマになるためのヒント。

コードを読むことは、読むことに過ぎません。取り組んでみて、乗ろうとしてみて、間違いを犯し、そして転ぶことによってのみコードベースを学ぶことができます。コードに取り組むことを阻害する知的な壁を建てないでください。自分の理解に対する自信のなさから最初は無力であった多くの優秀なプログラマを、私は見てきました。

やってみて、飛び込んで、勇敢に、コードを修正してください。

コードを学ぶ最善の方法は、そのコードを修正することです。そして、自分の間違いから学んでください。

では、あなたは何を修正すべきでしょうか。

コードを学ぶ際には、すぐに恩恵を得られて、何かを壊す(あるいは恥ずかしいコードを書く)可能性が少ない箇所を探してください。

システムを理解するのに役立つようなコードを探してください。

きちんと整理する機会を楽しんでください。がらくたに対して構造と健全さをもたらすことは価値があります。うんざりする練習だと思うのではなく、高い品質をもたらす機会だと見なしてください。それを教訓だと見なして、そこから学んでください。同じコーディングの誤りを繰り返さないためにはどうしますか。

基本的な学習の技法は、行って学ぶことです。書籍や記事を読んだり、オンラインのチュートリアルを見たり、プログラミングのカンファレンスへ参加したりすることは、すべてよいことです。しかし、あなたがその技術を使ってみるまでは、頭の中に概念が抽象的な集まりとして存在するにすぎません。

抽象的なことを具体化してください。つまり、飛び込んで、試してください。

理想的には、学習している最中に具体化してください。テストプロジェクトを初めて、知識を蓄積しながらその知識を使ってください。新たな言語を学ぶときは、すぐにその言語でコードを書き始めてください。読んだコード例を試してください。そのコードで色々と行ってください。間違いをして、何がうまくいって何がうまくいかないかを知ってください。

私は、自分が使っている言語との真の関係に熱心に取り組んでいます。それは、結婚に似ています。見返りが得られる関係ですが、努力を必要とします。

プログラミング言語の各概念がなぜ存在するかを解説する本。

  • 特定の言語やツールなどの知識は、変化が早くすぐに陳腐化する。意識して「変化しにくい知識」を学ばなければ、学んだことが価値を失う
  • 学び方の3つの柱
    • 比較から学ぶ
    • 歴史から学ぶ
    • 作ることで学ぶ
  • 失敗を伝える方法は大きく分けて2通りある
    • 返り値で伝える
    • 失敗したらジャンプする
      • 例外処理

たとえば作者本人が書いたドキュメントやソースが一番詳しいでしょう。しかし「難しい」「量が多い」「英語なので読めない」と口実を付けて、誰かの書いたやさしい解説を探したりしてしまいがちです。それは「オリジナルの肉は大きく て硬いから」といって、安全なのか傷んでいるのかもわからない、誰かの作ったひき肉を食べるのと同じです。気持ちはわかります。筆者も膨大な情報を前にして心が折れそうになることはあります。そんなときに使える戦略が3つあります。それは「必要なところからかじる」「おおまかにつかんで徐々に詳細化する」「端から順番に写経する」の3つです。

  • C言語の文字列は「文字列が始まるメモリ上の位置」だけを持っている。長さの情報を持っていないので、そこからどこまでが文字列かわからない
  • 文字列の終わりを、NUL文字を使って表現する。C言語のコード中では\0と表現する

クラスなんて「そう書けたほうが楽だから」という理由で作られた約束事にすぎないのです。物理法則や宇宙の真理ではなく、人間が決めた約束事なのです。ならば、どうしてそういう約束を決めたか言語設計者の意図を考えるのが理解の近道なのではないでしょうか?

  • クロージャという特殊な構文があるわけではない。関数を関数の中で定義でき、ネストできる静的スコープがあり、関数を戻り値で返したり変数に代入できる言語では、単に関数をネストするだけで状態を持った関数を作れる
  • クラスには、2つの相反する役割がある
    • インスタンスを作るためのもの – このためには、完結した、必要なものを全部持った、大きなクラスである必要がある
    • 再利用の単位 – 機能ごとの、余計なものを持っていない、小さなクラスである必要がある

タイポ。

  • これが画面の難行かを占めることがある
  • レプリケーション日ステム
  • のユーザーの中にはは自分の

メモ。

  • 自分が実装しているソフトウェアの標準化作業に関わることも重要だ
  • よくわからない部分がほとんどだった…。専門性が必要な分野のソフトウェアが多い