2018年08月12日

Go言語で作るインタプリタの献本をいただきました

オライリー・ジャパンの最新のGo本のGo言語で作るインタプリタの献本をいただきました。ありがとうございます。

本書は海外では出版社を通して出版されていないWriting An Interpreter In Goの日本語版です。誤解している人がかなり多いので捕捉しておくと、オライリー・ジャパンの本の多くは、USオライリーの本ですが、たまに別の出版社の本の翻訳があったり、描き下ろしもあります。別の出版社だと有名なのは退屈なことはPythonにやらせようで、描き下ろしだとゼロから作るDeep Learningや、僕の書いたReal World HTTPとかがあります。

本書の翻訳はとても読みやすく、どんどん読み進めることができました。翻訳の設楽さん、お疲れ様でした。

言語を作りたい人、かつて作ろうとした人も

原著は「短いページ数で実用的な言語を実装する」というのを目標に書かれています。本書のサンプルのmonkeyはどこかで見たような要素が満載の、RubyのようなJavaScriptのような言語で、前置演算子や優先順位にきちんと対応した数式、変数、if文、関数、return文を持った言語です。型も、整数、bool、nullに対応しており、4章の拡張では組み込み関数、文字列型、配列、ハッシュも実装します。お気に入りの言語風の文法を実装したい!と思っても(例えばループとか)、十分に基礎が解説されているため、応用をするのはやりやすいと思います。

プログラミング言語の要素というのは単純な単方向グラフにならず、要素が巡回するので、いくらテスト駆動開発の達人だろうが、スモールステップで開発するのが難しいジャンルのアプリケーションです。この本は動くものをどんどんスモールステップで作っていくので、非常にストレスが少なく楽しく作れます。この本はテストコードを書き、インタプリタのコードを書くというのを交互に行っていきます。

僕も、かつてFlex/Bison本を読んで、実際に趣味でインタプリタを作ってみたり(Ruby on Pythonとか)、数式パーサ(Excelのセルの数式の)を作ったりしたことがありますが、途中でずっとテストがグリーンにならない期間をずっと過ごしたり、なかなか動かなくてヤキモキして、苦しみを乗り越えてようやく動く、みたいな感じでした。本書ではうまい具合に「ここはTODOを書いて雑な実装でまずはパスして、あとで戻ってきて修正しましょう」ということが書かれています。こういう設計の分解方法はボトムアップじゃなかなか到達できなくて、熟練の業なんだろうなって思います。かつてコンパイラやインタプリタの本を読んだことがある人にも、目からウロコだと思います。僕はウロコがいっぱい落ちました。

言語を作りたい以外の人にもおすすめ

比較的短い分量で、スモールステップで開発していく手順で説明は進みますが、言語の要素としては基礎的な、lexerでトークンに分けて、parserでASTを作り、evaluatorで実行する、という王道な構造になっています。本書はインタプリタを作る本ですが、これらの技術要素というのは処理系を作る以外にもいくらでも応用例があります。

例えば、字句解析だけは他のものを利用しつつ、そのさきの部分は自作する、みたいなことも可能です。evaluatorの代わりに、情報を出力する変換器をくっつける(本書のInspect()の応用みたいな)ことも可能です。

例えば、ちょっとしたテキストのパースとか、データの解析にも応用できます。JSONやTOMLのようなオリジナルのデータ・フォーマットを作る、みたいなこともできるでしょう。本書でもちょっびっと触れられていますが、JavaScript界隈の最近の発展もJS自身のパーサがJSで作られたことからカンブリア爆発が起きているのでは、と僕は思っています。jslintのフォーマッター、minify、concatツール、prettierのようなコードフォーマッター、babelのようなトランスパイラまで、すべてはこれらの技術要素が少なからず貢献しています。

このように、本書を読んで身につく技術というのは、身につければ今まで自動化が難しかったようなものをガンガン自動化していくための武器になります。夢が広がりますね!

Goは擬似言語としても有用というのは本当だろうか?

昔僕が読んだ本はparser部分はC言語を生成する特定のパーサジェネレータを前提としていたため、他の言語で実装するにはどこを参考にすればいいのか難しい、ということがありましたが、この本が良いのは標準ライブラリだけを使っていて、なおかつコードジェネレータを使わない(昔はgo tool yacc添付されてた)説明になっています。そのため、ここで学んだことを他の言語で応用するのは比較的やりやすいと言えます。

とはいえ、上記のような感想を持たれる方も多いでしょう。僕もReal World HTTPGoならわかるシステムプログラミングでは、「Goはシンプルな言語なので、動く擬似言語として他の言語のユーザーでも難しくないよ」ということを書いたことがあります。

自分の書いた本では証明にならないと思うので、せっかくの機会なので、Python 3.7で3章まで実装してみました。Pythonは一番書いていたのは2.5とか2.6の時代で、その後は2.xと3.xの両対応のコード、みたいな実装ばかりしていました。Python 3で増えた機能を積極的に使ってみるということで、漸進的型付けにチャレンジしてみました。ついでに、環境構築の仕方もQiitaにアップしています。

実際にやってみると、言語ごとの違いが致命的になることはありませんでした。Goにしかない文法要素とかもあまりないですしね。ただ、やってみて気になったのが、Goのinterfaceが、他の言語でいうnullableが自動でつく、という点ですね。全部にnullになる可能性があることを明記していくか(Pythonのmypyだと、Optionalをつける)、NullObjectを作るか・・・僕の実装は後者にしています。あとは、astパッケージのサンプルの、プライベートなstatementNode()関数を使ったインタフェース指定も他の言語ではみないやり方なので、明示的にインタフェースを実装する宣言が必要になるでしょう。

あと、Pythonならでは、というのだと、インタプリタ言語で上から実行しつつ型を作っていくため、前方参照ができない、というのが一つあります。あとは歴史的経緯で、Python 2.3まではbool型がなく、0/1の数値を使っていたため、isinstance(True, int)が真になってしまう。このあたりは宣言の順番だったり、比較の順番をちょっと修正する必要があります。Environmentでは親の環境を属性で持つので自分自身の型を属性で持ちますが、Pythonとmypyはメンバーの評価を先に行ってからクラスができあがるため、そのまま書くと未定義のエラーになります。属性の方は文字列で"Environment"と書いておけば大丈夫、と@methaneさんからアドバイスもらいました。

ちなみに、Rustでやられている方もいますね!

Goのサンプルコードは少し改善の余地あるものの、良い本です

一部、サンプルコードの書き方は気になるところがありました。もし自分がレビューアだったら(翻訳ではなくて原文に対してですが)指摘していただろうなという点は以下の通りです。

  • iotaの定数の最初の値を_で読み捨てているけど、これなくても良い気が。初期値が0であると壊れるようなコードもないので。
  • 配列(というよりもスライス)は、nilであれば長さゼロのスライスとして扱われるので、わざわざ初期値を与えなくてもいいのでは。
  • Goで推奨されているテーブルテストが多様されているのは良い傾向だけど、ループごとにt.Run()を呼ぶとエラーがわかりやすくなってさらに良いです。PythonにもsubTestというのがあります。
  • エラーと評価結果を同じreturnで返しているのはどうなんだろうか?多値返却できるし、エラーは混ぜないほうが良いような

まあ、すごく細かい内容なので、大勢には影響はないです。とても夢が広がる内容でよかったです。今まではC言語だったり、関数型言語だったり、特定のパーサジェネレータをターゲットにしていた本が多かったジャンルで、Goで実用的な言語が作れる本というのは貴重です。僕の二冊の本(HTTP、システムプログラミング)に続いて、日本で「Goで学べる」シリーズの三冊目といえるでしょう。

原著者の次の本はバイトコードを使ったコンパイラの本ですね。こちらもそのうち出てくるんでしょうか?楽しみです。

posted by @shibukawa at 18:29 | TrackBack(0) | 日記 はてなブックマーク - Go言語で作るインタプリタの献本をいただきました
この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/184154972
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック
検索ボックス

Twitter

www.flickr.com
This is a Flickr badge showing public photos and videos from shibukawa.yoshiki. Make your own badge here.
<< 2018年08月 >>
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
最近の記事
カテゴリ
過去ログ
Powered by さくらのブログ