Book

「Go言語でつくるインタプリタ」を読んだ

「Go言語でつくるインタプリタ」を読み終えました。

この本は、私のようなGo言語初心者のでも理解しやすい構成で、プログラミング言語の構築に必要な字句解析や構文解析の基本的な概念を学びながら、動くインタプリタを完成させることができます。 プログラミング経験があるものの「字句解析」や「構文木」という用語はなんとなく聞いたことがある程度だった私にとって、実際に手を動かしてプログラムを動作させることができ、学びと共に達成感もひとしおの一冊でした。

多くのハンズオン本では、「インタプリタの一部だけ」を実装することに留まりがちで、最終的に完成するのが部分的なコードであったり、動作しない例も多くあります。 しかし、この本は最初から最後まで実際に動くインタプリタを作り上げることができ、その後にいろいろ試してみたりもできます。 実際私はREPLだけでなく、ファイルを読み込んで実行させるように改造して楽しみました。 このような「動くものを作り上げる」体験は、プログラミングやシステム理解にとって重要なポイントだと思います。

具体的には、以下のようなセクションごとの段階的なステップを経て、コード全体が構築されていきます。

字句解析: 「トークン」や「字句解析器(Lexer)」という基本的な概念から始まり、最初のコードの実装を通してデータがどのように分解されるのかが明確になります。

構文解析: 「構文解析器(Parser)」を使ってAST(抽象構文木)を生成することで、プログラムの文法構造がどのように理解されるかを深く掘り下げます。

評価器: 最後に、構築したASTを評価し、インタプリタとして動作する一連のフローを構築していきます。

Go言語初心者でも学びやすい理由の一つに、各章でのコードと概念の説明が一貫して丁寧に行われている点が挙げられます。 例えば、字句解析の章では一つひとつのトークンの分解と構造を詳しく説明しており、構文木(AST)の組み立ての理解が進むような工夫がされています。 構文解析や評価に進むに従い、少しずつ難易度が上がりますが、各章で順を追って理解していけるため、初心者にとっても安心です。

また、テスト駆動開発であることも理解が非常に進みました。 私は普段コードをあまり書いていないので、テスト駆動開発の恩恵に預かれていなかったのですが、先にどういうアウトプットが想定されるかが提示されるのは理解の助けになりました。

時間はかかりましたがなんとか読破できましたので、個人的なおすすめの読み方を提示しておきます。

コードを写経する

手を動かしてコードを書くことは、多くの人にとってこの本を読む上では必須だと思います。手稲にコードが記載されていますが、それでもぼんやり写経してると飛ばしたり書くところを間違えたりして、それを解消するプロセスがまた理解につながったりします。 電子書籍だとコードをコピー&ペーストできてしまうこともありますが、ここは実際に自分の手で入力して試行錯誤するのがおすすめです。

理解のズレに注意

インタプリタの実装は、エラーが起こりやすい分野でもあります。 例えば、字句解析のセクションではトークンの扱いを間違えやすく、構文解析ではASTの構造の間違いが結果に影響します。 実行時にエラーが発生した場合、なぜそのエラーが起きたかを丁寧に追っていくことが大切です。 その点、ユニットテストも提示してくれているところは非常にありがたいです。ユニットテストを頼りに自分の理解を補強することができます。

各章ごとに振り返る

一気に読み進めず、各章で実装した機能がどのように働くのかを自分なりに理解する時間を取ることをお勧めします。各章が次の章の基礎になるため、途中で理解が浅い部分があると後の章でつまづきやすくなります。

総評

「Go言語でつくるインタプリタ」は、Go初心者から中級者に向けた実践的な内容で、言語構築の基礎を学びたい方に非常におすすめの一冊です。 特に、プログラムが動作し、抽象的な概念を実際の動くコードとして実現できる達成感を味わうことができます。 字句解析や構文木のような「聞いたことはあるけれど、実はよく知らない」という分野に一歩踏み込めて、さらにGo言語の勉強にもなる本書は、自分のレベル感にはちょうど良い一冊でした。 ちなみにジェネリクスは無い時代の本なので、その辺を改良するのも良い勉強になるかもですね。

また、本書には続編があります。 https://compilerbook.com

今度はインタープリターではなくコンパイルして仮想マシン上で動作させるそうです。 こちらはまだ日本語訳されていませんが、時間を見つけて取り組んでみたいと思います。

「入門監視」を読んだ

1年ほど積読にしてた「入門監視」を読み終えました。

この本は監視ツール個別の話はほとんどなく、監視をどう設計すべきかが記されています。 私自身、監視を色々見たり設定したりしてきましたが、考え方の答え合わせができて楽しかったです。

まずはアンチパターンをチェックする

この本を買う前に1章だけでもみてもらって、自分がアンチパターンにハマっていないかを是非チェックして欲しいと思います。

流行りのツールにOSメトリクスでとりあえずアラート仕掛けたりしていた自分には胸をえぐられる章でした。 心当たりのある人は目次を見ただけでもグッとくると思います。

 1.1 アンチパターン1:ツール依存
    1.1.1 監視とは複雑な問題をひとくくりにしたもの
    1.1.2 カーゴ・カルトなツールを避ける
    1.1.3 自分でツールを作らなければならない時もある
    1.1.4 「一目で分かる」は迷信
1.2 アンチパターン2:役割としての監視
1.3 アンチパターン3:チェックボックス監視
    1.3.1 「動いている」とはどういう意味か。「動いている」かどうかを監視しよう
    1.3.2 アラートに関しては、OSのメトリクスはあまり意味がない
    1.3.3 メトリクスをもっと高頻度で取得しよう
1.4 アンチパターン4:監視を支えにする
1.5 アンチパターン5:手動設定

自分の経験を答え合わせをする

自分はこれまでWebシステムを中心に監視の設定を見たり行ったりしてきました。 世の中には色々なシステムがあり、色々な事情もあるとは思いますが、これまで経験してきた監視の経験を本書で答え合わせをしてみました。

所属組織の標準的な監視パッケージに乗っかったこともあれば、自分で1から設計したこともあります。

どこかで見聞きしたものなのかも忘れましたが、自分で監視を設計するときは下記のポリシーを大切にしてきました。

  • 利用者より先に気づく事
  • ユーザーの実際の不便を監視する事

「動いている」を監視する

サービスが元気に動き続けることがベストではありますが落ちることも必ずあるのがシステムの世界です。そんな時にサービスの不調にいち早く気づくことが監視の一番の役目であると考えています。

なのでURL監視を中心とした監視を組みつつ、可能であればビジネス的に一番熱いユースケースやユーザーの不便に最もつながりそうなユースケース、 つまりユーザーの信頼を失うことにつながりそうなユースケースを実際にトレースするような監視を作ってきました。

また、この監視が動いていればとりあえずシステムとしては健全であるというラインが担保できていると、システム運用にかかるストレスが非常に低減されます。

例えばポイント系のシステムでポイント付与までのユーザーの行動をトレースするようなものを、ユーザー登録が命のようなサービスであれば実際にユーザー登録を行うようなものを外部から実際に自動的に行うような監視を行ったりしました。

なので本書でいう「動いている」を監視できていたと思います。

お手製の監視システムでOSメトリクスを監視

一方で、OSのメトリクスに関してはついついCPU 80%とかロードアベレージ10とかを閾値とした監視を手癖のように設定しがちではありました。振り返ってみてもCPUやロードアベレージなどのメトリクスによるアラートにより実際に行動を起こす事は少なく、 URL監視などの外形監視の補助として使うことが多いです。

そして監視ツールの選定ですが、監視Saasが成熟してきている今日、未だに本格導入を試みたことがありません。AWSだとCloud Watchをベースにした監視などを行ったことはありますが、当時はカスタマイズ性にいまいち満足がいかなかったという記憶があります。 そういった古い記憶から無意識に監視Saasそのものを敬遠しがちになっていたのは否めません。

直近ではPrometheusを導入して、それはそれで満足はしていますが、同じことを監視Saasでやれなかったとはいえません。監視Saasも時が経つにつれ洗練されているはずで、コスト対効果を鑑みてもっと積極的に導入を考えても良かったと反省する部分もあります。

この辺りは本書でいうアンチパターンにハマっていたと思います。

まとめ

自分の経験を本書と照らし合わせて答え合わせのできる楽しい読書でした。

監視は作り手の自由度が高い分野であると思います。下手をするとアラートだらけになってしまう所を本書の指針に沿って設計する事で、みんなが幸せになれる監視を設計できるかと思います

「統計学が最強の学問である(数学編)」で機械学習の入り口に連れて行ってもらおう

「統計学が最強の学問である(数学編)」を読み終わりました。機械学習を学ぶための数学の知識を叩き込んで、機械学習の入り口まで連れて行くぞという著者の意志を強く感じる本でした。

記号論理学から始まって、連立方程式、線形代数、微分積分まで、幅広い知識の中から機械学習に必要なエッセンスを詰め込みながら、機械学習・ディープラーニングの入り口まで連れて行ってくれる一冊になっています。

内容

この本の流れを簡単にまとめると下記のようになります。

  1. 簡単な確率、記号論理学、集合から最終的には迷惑メールフィルタでも用いられていたナイーブベイズ
  2. 1次、2次の関数を学び、ちょうど良い数を求めるための平方完成
  3. 二項定理から二項分布、対数、ネイピア数について
  4. たくさんの数を効率的に表記するためにΣ、ベクトル、行列
  5. ちょうど良いところを探すための微分、確率密度関数を理解するための積分
  6. 線形代数と微積分を同時に使うことで機械学習、ディープラーニングの入り口へ!

やはりクライマックスはこれまでの知識を積み上げて機械学習の入り口が見えてくる6章です。特に行列、偏微分のありがたみがわかった最小二乗法の解法はしびれました。

行列、偏微分を用いた最小二乗法とnumpy

2章では訪問回数と契約件数のデータを元に比例関係の式を最小二乗法で2章で学んだ最小二乗法は平方完成により答えをめました。 6章ではこれまで学んできた知識、つまり微分、行列を使った解法を解説してくれています。

下記が2章の例示されていたデータになります。

訪問回数(単位:100回)契約件数(単位:1件)
110
240
382

上記の表で表されるモデルが訪問回数をx, 契約件数をyとした場合に直線で表されるとします。 この場合にモデルを表す式は下記のようになります。

\[ y = a + bx + \varepsilon \]

εが誤差でこの誤差を最小にするa, bを求めます。 データは3つありますので、それぞれx, yに代入すると3つの式が出てくるわけですが、これを行列で表現すると3つの式ではなく一つの行列式で表すことができます。

\[ y = X\beta + \varepsilon \]

X, y, β,εはそれぞれ下記のような行列になります。

\[X = \begin{pmatrix} 1 & x_1 \ 1 & x_2 \ . & . \ . & . \ 1 & x_n \end{pmatrix} , y = \begin{pmatrix} y_1 \ y_2 \ . \ . \ y_n \end{pmatrix} , \beta = \begin{pmatrix} a \ b \end{pmatrix} , \varepsilon = \begin{pmatrix} \varepsilon_1 \ \varepsilon_2 \ . \ . \ \varepsilon_n \end{pmatrix} \]

εの二乗和が最小になるようなa, とbを求めるのが最小二乗法です。 行列の場合、誤差の二乗の和を求める方法としてはεの転置行列とεの内積で表現することができます。

\[ \varepsilon^{ \mathrm { T } }\varepsilon \]

この二乗和が最小になる時のa,bを求めるためにβで偏微分してやります。

\[ \frac{ \partial \varepsilon^{ \mathrm { T } }\varepsilon } { \partial \beta } \]

ここからは、この章にたどり着くまでに得た行列や偏微分の知識を駆使して進めて行くのですが、 詳しい解法は是非本書で確認してみてください。結果として下記の式が得られます。

\[ \beta = (X^{ \mathrm { T } }X)^{-1}X^{ \mathrm { T } }y \]

\[ (X^{ \mathrm { T } }X)\beta = X^{ \mathrm { T } }y \]

この式に今回の例を代入すると、下記のようになります。

\[ \begin{pmatrix} 1 & 1 \ 1 & 2 \ 1 & 3 \end{pmatrix}^{ \mathrm { T } } \begin{pmatrix} 1 & 1 \ 1 & 2 \ 1 & 3 \end{pmatrix} \begin{pmatrix} a \ b \end{pmatrix} = \begin{pmatrix} 1 & 1 & 1 \ 1 & 2 & 3 \end{pmatrix} \begin{pmatrix} 10 \ 40 \ 82 \end{pmatrix} \]

ここまでくるとPythonで機械学習をやる上で定番のnumpyを使い、逆行列を用いて傾きと切片を求めることができます。 この本で学んだ数学の知識が、自分がこれまで学んできた機械学習の定番、numpyと出会った瞬間でした。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import numpy

x = numpy.array([[1, 1], [1, 2], [1, 3]])
y = numpy.array([10, 40, 82])

left = numpy.dot(x.T , x)
right = numpy.dot(x.T,  y)
inv_left = numpy.linalg.inv(left)
beta = numpy.dot(inv_left, right)
print(beta)

結果は下記のようになります。

1
[-28.  36.]

データ(今回の場合x, y)が増えていっても、この式に当てはめれば容易に最小二乗法を用いたモデルを導くことができます。

まとめ

自分自身はこの本を読む前に機械学習の本を読み始めてしまっていましたが、これから学習する方には是非ともお勧めしたい一冊です。 この本で得た知識を携えて、なんとなく通り過ぎているこれまでの知識をもう一度ブラッシュアップしたいと思います。

挫折者にも優しい「実践Scala入門」を読んだ

Scalaは昔少し勉強して挫折した経験があります。月並みにいえば、その時こういう本があったらなぁという感想です。

そもそも会社でのポジションはSREなので、Scalaを実務で書くことはほとんどありません。Pythonは書くシチュエーションがありますが、関数型を多用することもありませんでした。

本書の読了が見えてきた頃からこの本を片手にScalaでCodility の問題を解く会社内の集まりに参加させてもらっています。Atcoder にも参加するようになりScalaプログラミングを楽しんでいます。

構成

Scalaの基本的な使い方からScalaプロジェクトを管理する上で必須のsbtやユニットテストなども含まれており、業務でScalaを使い始める人もは網羅的な内容となっています。 もちろんこの本を読んだだけでScalaを使いこなせるわけではなく、最終章の締めくくりにあるようにどんどん書いていくことが必要ですが、この本の内容を知っていたらどれだけとっかかりがスムーズだろうとか思います。

新人が入ってくるこの時期、Scalaをメインの言語として扱っている会社はこの本をとりあえず渡しておくのもありかと思います。

感想

そもそものきっかけはScalaでバックエンドを書いている会社に入ったのでScalaかけるようになりたいなと購入しました。 普段はPythonを利用していて、昔はJavaを書いていた頃がありましたが、基本的にはインフラ関連の業務が多く、Terraformと戯れることが多い毎日です。

この本の前提である1つ以上のプログラミング言語に慣れていることという点はクリアしていますが、第2章のScalaの基礎や第4章のコレクションについてはなかなか苦労しました。ここはひたすら写経ですね。

苦労したとはいえ、著者の方々がScalaに対して敷居を下げようと努力している所は随所に感じました。 サンプルプログラムや図を用いたり言い換えを行ったりして置いてきぼりにならないような配慮が随所に見受けられました。

例外処理や並列処理にも言及してあるのも良買ったです。特に例外処理はTryとかEitherとかこれまでの経験とは一味違う機構をScalaは備えているので助かりましたし、そもそも業務では必須の知識なので。本書の構成としても第3章という前の方に置いてある点から重要視しているのかなと思いました。

並列処理についてもサンプルを写経することで理解が進みました。ただ、競技プログラミングをやっているだけではなかなか登場することがないので、もうちょっと何らかの他の本を読むなりして補強していかないといけないと感じている部分です。

非機能系としてはログに関しては言及がなかったように思います。是非ログについても取り上げて欲しいですね。

そして9章、10章では何をとっかかりに調べれば良いかわからない応用的な部分や、より良いコーディングの指針などが書いてあって、これでScalaはとりあえず書けるという気にさせてくれました。 一旦かける気になったら、あとは書くだけ。おかげで前述の通り、CodilityやAtcoderでScalaプログラミングを楽しんでいます。

まとめ

初学者に優しい本書だからこそ、誤植が一部あった点が残念でした。 技術評論社さんへ連絡したらすぐにサポートページを更新してくれましたが、そもそもサポートページにたどり着くまでのステップはないに越したことはありません。

ただ、その点を差し引いても非常に網羅的で、Scalaへのいろんな障害を乗り越える上で非常に有用な本でした。

「Docker/Kubernetes実践コンテナ開発入門」を読んだ

OreillyのDocker本に続いて読んだのが、現時点では比較的最近出版された本書でした。

出来るだけ新しいDocker本で最近の情報で知識をアップデートしたかったのと、Kubernetesの説明が充実してそうというのが本書を手に取った動機です。

Dockerに正式採用されたKubernetesと、Swarmの違いなんかも体験できればなと思いました。

内容

Dockerの基本的な使い方から入るところは、先に読んだOreilly本と同じでしたが、目論見通りOreilly本の時点から色々変化があった事を知ることができました。 大きな変化はKubernetesの正式採用などがありました。 小さな変化ははDockerコマンドについてのコラムにあった docker container というコマンド形式で、 以前は省略していた “container"の指定が現在は推奨されつつある等です。 dockerコマンドではpruneオプションなんかも知ることができました。

構成としてはDockerの基本を学び、オーケストレーションを体験し、実際に運用する上での知識をつけていく流れなのですが、 サンプルで作成したToDoアプリを題材に、Swarmを経て Kubernetesへ載せていく流れでオーケストレーションについての知識が深められ非常に分かりやすかったです。 また、本番で使っているからこその著者のDockerについての考え方や知見が随所に散りばめられており、 後半の章、特に9章での軽量なDockerイメージの作り方はDockerの内部構造を意識する上でも非常にためになりました。

特に面白かった所

docker-composeで作成したToDoアプリが、最終的にKubernetesに載る所が、1つのクライマックスかと思います。 本書ではGCPでKubernetesを利用していますが、私はEKSでサンプルを試していきました。 ロードバランサの取り回しなど、細かい点は考慮が必要ですが、どちらのプラットフォームでも動作させれる点が、Docker, Kubernetesの強みであると実感できました。

また、コラムが非常に充実していて、日々運用する上で何に困って、どういうツールで解決していったかを知ることができ、運用の雰囲気を知る上で有用でした。

まとめ

Dockerの進化を感じつつも、実践という名を冠しているだけあって、著者が本番でDockerを運用し、格闘して得た知識が詰まっています。 私自身はKubernetesに移行するかは検討段階で、まだまだやる事が山積みですが、本書を片手に現在のDockerの運用を改善しつつ、来るべきオーケストレーションに備えたいと思います。