SICP:二度読む価値がある唯一のコンピュータ科学書?(2010年)
(simondobson.org)- ある学生に夏の読書として貸した本をきっかけに、Simon DobsonはSICPが自身のキャリアと研究上の関心に最も大きな影響を与えたコンピュータ科学書であることを改めて確認した
- Pascal中心の入門教育とは異なり、この本は値・名前・束縛・制御から出発し、プログラミングが何になり得るのかを示す
- lambda抽象、高階計算、ストリーム、遅延評価、インタプリタとコンパイラ、ガベージコレクション、仮想メモリ、機械語、ドメイン特化言語に至るまでをSchemeの中で結びつけている
- 最大の影響は、複雑なシステムを複数層の言語で構成する階層化設計と、コンピュータ科学を「何であるか」より「どう行うか」の学問として捉える視点にある
- 1988年に買った本が2010年になっても実用的に再読する価値を保っており、SICPはコンピュータ科学における息の長い基礎書であり続けている
SICPとの最初の出会い
- Simon Dobsonは学生に夏のあいだ読む本として Structure and Interpretation of Computer Programs を貸したことをきっかけに、この本が自分にとってコンピュータ科学全体の中でもっとも根本的な著作に近いことを思い出した
- 正式な書名はHal AbelsonとJerry Sussmanによる Structure and Interpretation of Computer Programs で、MIT Pressから1984年に刊行され、SICPとしても知られている
- この本は今も出版が続いており、全文がオンラインで提供されている
- DobsonはNewcastle upon Tyneで最初の学位課程2年次に最初のプログラミング科目を終えた後、推薦図書としてこの本に出会った
- 当時コンピュータ科学の中で自分の道を探していた彼にとって、SICPはPascalに代表される「当時のプログラミング」ではなく、あり得るプログラミングの形を示してくれた本だった
Schemeの中で積み上げられた概念
- SICPはプログラミングの基本要素である値、名前、束縛、制御から始まり、幅広い主題へと拡張していく
- lambda抽象と高階計算
- 計算内容を含む複雑なデータ構造
- モジュール性、変更可能性
- ストリーム
- 遅延評価
- インタプリタとコンパイラの構成
- 記憶域管理、ガベージコレクション、仮想メモリ
- 機械語
- ドメイン特化言語
- 扱う範囲は面食らうほど広いが、著者たちの文章と構成のおかげで一貫性を保っている
- とりわけ、すべての概念をSchemeという一つの言語フレームワークの中で扱い、前で学んだ内容を土台に次の概念を積み上げていく
言語設計として見るプログラム設計
- SICPで大きな影響を与えた二つ目の特徴は、Hal AbelsonとJerry Sussmanがあらゆることを言語設計の練習として見ている点にある
- 本書は、複雑なシステムを複数レベルの言語で構成する階層化設計を強調している
- 各レベルは、そのレベルで原始的と見なされる部品を組み合わせて構成される
- あるレベルで作られた部品は、次のレベルの原始要素として使われる
- 各レベルの言語は、その詳細レベルに応じた原始要素、結合手段、抽象化手段を持つ
- 階層的抽象化それ自体はコンピュータ科学者にとって馴染み深いが、ここで重要なのは各階層がプログラム可能でなければならないという見方である
- この観点では、階層は単に情報を隠すための装置ではなく、計算と変換を扱うための手段である
- 主流のプログラミング言語では、このような階層化は言語自体の拡張につながりにくい
- Javaは上から下までJavaであり、クラスやライブラリはあっても新しい制御構造はない
- 特定ドメイン向けに専用の言語構造が有用でも、言語の中で簡単に追加することは難しい
- 逆に、あるドメインで特定の構造を使わせたくなくても、言語の中では取り除けない
- Java-MEは小さなデバイスで動かすために一部の機能を削ったが、コンパイラを書き直さずにできるやり方ではない
「何であるか」より「どう行うか」
- 三つ目に重要な影響は、コンピュータ科学が実際に何を扱うのかについてのSICPの見方である
- SICPはコンピュータ革命を、考える方法と考えを表現する方法の革命と捉える
- 本書はこれを**手続き的認識論(procedural epistemology)**として説明する
- 古典数学が「何であるか」を精密に扱う枠組みを与えるなら
- 計算は「どう行うか」を精密に扱う枠組みを与える
- Dobsonは、コンピュータは新しい顕微鏡のように既存のアプローチを助けると同時に新しい科学を切り開く、という見方を取ってきた
- コンピュータ科学における「どう行うか」という側面は、さまざまな領域で再び現れる
- 配置された現象を継続的に反映しながら適応できるセンサーネットワークの動作記述
- Web全体から採掘・結合された大規模データの解釈
- 科学的方法とプロセスを自動化するための取り込み
- こうした領域の豊かさは、パッケージソフトウェアよりもプログラミング言語による統合を促し、R のような言語によってインターフェースと構造を柔軟で実験可能なものに保つことを可能にする
古い本が今なお読まれる理由
- Dobsonの本の見返しには1988年9月という購入日が書かれており、2010年時点でほぼ22年前の本がなお関連性を保っている
- 彼はSICPを、単なる歴史的関心からではなく、有用に再読できるその年代のコンピュータ科学書としてほぼ唯一のものだと見ている
- 数学書では長く通用する内容は珍しくないが、アイデアの動きが速く一時的な主題も多いコンピュータ科学では珍しいことだ
- SICPの内容がほとんど古びていないことは、この本がコンピュータ科学の中核概念をよく捉えていたことを示している
- こうした理由から、SICPは二度以上読む価値のある数少ないコンピュータ科学書であり、物理学におけるFeynmanの Lectures on Physics のように、その分野の本質をアクセスしやすい形に蒸留し、時の試練に耐えた本として評価されている
- 2024年1月27日の更新では、この本は Structure and interpretation of computer programs の項目として、annotated Lisp bibliography にも含まれている
1件のコメント
Hacker News のコメント
SICP のような「古典」はプログラム設計について語っているが、今ではシステム設計のほうがはるかに重要な能力に見える
分散システムが「コンピュータサイエンス」に含まれるのかは分からないが、実際にはより頻繁に解く必要がある問題だ
システムは可能な限りシンプルに作り、可観測性ツールで設計が足りない箇所を見つけ、その後必要になったときにデータ構造や「コンピュータサイエンスっぽい」解法を取り出す、というやり方をしている
ほとんどの場合、ビッグオー記法と実行時間計算量は重要ではなく、配列と高速な CPU で多くの問題を解決できる
性能問題が起きても、まずはプロファイリングでボトルネックを見つけるべきだ
コンピュータサイエンスは、CPU のメモリキャッシュがどう動くかを十分に教えてくれない
すばらしいグラフアルゴリズムは実行時間計算量が良くても CPU キャッシュを台無しにして、キャッシュ利用の良い配列より遅くなることがある
実際によくある問題は、フォールトトレランス、分散ロックとキューの正確性、システムのスケーラビリティを扱うことだ
コンピュータ工学/電気工学のバックグラウンドなので、偏りがあるかもしれない
CPU メモリキャッシュは 30 年前、CS 学部の最初の学期に Hennessy と Patterson の本で学んだし、今でも使われていると理解している
フォールトトレランス、分散ロックとキューの正確性、システムのスケーラビリティも学部の CS で扱ったし、特別なコンピュータ工学/電気工学の背景ではなかった
今でもフレームワーク、データベースエンジン、バージョン管理ツールを作る仕事はあり、そうした仕事ではアルゴリズムやデータ構造のような深い CS 知識が毎日求められる
しかしそのような職は以前より少なくなり、アプリのために DB エンジンを自分で実装するよりも Postgres を使う場合が多い
仕事の大部分はビジネスロジックの実装であり、データベースが内部でどう動くかを知っていればより良い結果を出せるが、インデックスがディスク上にどう保存されるかを知らなくても、動くソフトウェアはたくさん作れる
多くの CS 卒業生は自分の仕事がフレームワークを書くことだと勘違いしているが、実際には既存のフレームワークを使い、ビジネスロジックを実装しながら、CS の背景によってそのフレームワークを深く理解する必要がある
データはディスク上の「ページ」として存在し、RAM には固定数の「ページスロット」がある
ディスクと RAM の間でページを移動するのは遅いので、できるだけ減らさなければならない
そのため、些細に見える問題も面白くなる。古典的なコンピュータサイエンスには「ジョイン」という概念が特にないが、名前を付けるほど複雑ではないからだ
アルゴリズム研究を純粋な本質のように考えがちだが、アルゴリズムの効率は特定のデータとハードウェアの文脈でのみ意味を持つ、と見ることもできる
だから仕事は面白くなり、あらゆる場所にライブラリや料理本式の解法だけを適用すればよいわけではないため、アルゴリズムの専門性はいまも有用になる
いま小さな変更を担当しているコンポーネントで苦労しているのだが、状態が不必要に多く、2 つの抽象化を同時に扱っている
ファイルを処理しながらファイルシステムとデータベースを状態保存に使っているのだが、設計があまりにひどくて驚いた
これまで通りに継ぎ足して、さらに理解しにくくすることを避けるために数日を費やした
プルリクエスト文化は、実際のコードについて深く考える余裕もなく、どんなゴミでも承認させるものになっているように見える
対面のコードレビューが戻ってきてほしい
2021 年に出た本
記事の無料コピーへのリンクが切れている
https://mitp-content-server.mit.edu/books/content/sectbyfn/b...
https://web.mit.edu/6.001/6.037/sicp.pdf
今日まで公式PDF版を見たことがなかった
2001年ごろはHTML版だけが無料で、誰かがTeXinfoに変換していた: https://www.neilvandyke.org/sicp-texi/
今SICPを進めたいなら、MIT SchemeやDrRacketでコードを実行できる: https://www.neilvandyke.org/racket/sicp/
現行リリース(v12.1)は、Intel CPUでSequoiaを実行するMac、またはRosetta経由のApple siliconで動作する
ただしネイティブコードコンパイラは少し壊れていて、SICPにはおそらく必要ない
Monterey以前のmacOSでは動いていたようなので、Apple提供の依存関係が変わったのかもしれないが、追跡はしていない
MIT Schemeが必須ではなく、コンパイルで苦労したくないなら、Racketのほうがよい選択かもしれない
明示的なSICPモードがあると記憶している
GNU Guileで進めてみたが、GuileとMIT Schemeの間に細かな構文の違いがあり、かなり面倒だった
MITの原本より書式がよい: https://sarabander.github.io/sicp/
以前はパッケージがあったが、ほぼ20年間メンテナンスされていない状態
一方でDrRacketには、それらの問題を解くための専用パッケージがある
AbelsonとSussmanがこの本の内容を教える1986年録画の講義を見ることができる
抽象化を複数の層として作り、まとめる方法についての説明は、今でも個人的にもメンタリング時にも役に立つ
動画ではlesson 3Aの1:07:55あたり
https://m.youtube.com/playlist?list=PLE18841CABEA24090
The Elements of Programming Styleは3回読む価値があり、それよりはるかに何度も読み返して助けられた
興味があれば、2010年に書いたレビューがある: https://reprog.wordpress.com/2010/03/06/programming-books-pa...
https://elementsofprogramming.com/
SICPで一番好きで、何年も記憶に残っている部分は、願望的プログラミングというアイデアだ
低レベルのルーチンがすでに存在すると願うようにして、上から下へ何かを作っていく方法である
それから実際にその低レベルのルーチン群を作り、底まで降りていく
この考え方はテスト駆動開発と非常によく合うと思う
あったらよい機能を対象に先にテストを書き、その願望を満たしにいくというやり方だ
たいていの開発者は下から上へ作り、結局誰も欲しがっていなかった何かを手にしているように見える
まだ本当の性質を知らない対象を偶然願ってしまうことがあり、そうすると底の部分に脆い混乱が生まれる
たいていそうなる。物事のアルゴリズム的性質は、まれにしか直感的ではないからだ
下から始めるのは、「魔法が存在してほしい」ではなく、実際に手元にあるクォークから始めるようなものだ
魔法はなく、底に到達すると魔法の粒子ではなくクォークがあり、その過程で2つの物理学の間を変換する助けになる文脈上の手がかりも失ってしまう
どちらのアプローチにも有用性はある。深い問題を解くには、ときに大胆に願う必要があるからだ
ただ個人的には、魔法を最上位のすぐ下の層に置くほうを好む
下から上へ作ったあと、ビジネスロジックの直前に、ビジネス言語との相互変換を行う便利用の魔法レイヤーを作る方式だ
そうすれば調整可能で、下まで絡み合った混乱を作らずに済む
まず適切に見える組版/タグ付け方式を書き、マークアップにふさわしいプログラミング方式――つまりマクロ――を構想してから実装に入った
OpenSCADでG-codeをモデル化するライブラリを作ろうとしている自分の作業にも、似たやり方を試している
最近「純粋な」OpenPythonSCADで書き直したので、使えるものになってほしい
Pharoを試してみるとよい
SICP は、コンピュータサイエンスを学ぶときに最初の本として読むのに最適な本である
何年も趣味でプログラミングをし、構造化プログラミングの本や Pascal から Common LISP までさまざまな言語に触れたあと、学部のコンピュータサイエンス課程で Abelson & Sussman を使ったが、目を開かされた
Scheme の単純さ、美しさ、対話性を示しながら、コンピュータサイエンスとは複数の種類の抽象化を階層的に積み重ねることなのだと教えてくれる
手続き抽象化とデータ抽象化から始まり、自分でドメイン特化言語を定義してそのコンパイラを実装し、ソフトウェアの中で新しいハードウェアを定義するところまで進む
すべてがあまりにも自然に見え、本当の達人だけがそう見せることができる
ただし、第1版や最近の版ではなく、第2版を買うべき
最近の版は Scheme の代わりに Python を使っているが、いまひとつ
SICP を本当に好きになりたかったが、Lisp が足かせになった
Haskell と Standard ML は好き
似た経験をした人がいるのか気になる
SICP と精神は似ているが、別の言語を媒介に使う本があれば面白そう
JavaScript で SICP をやりたいわけではない
著者は Scheme の代替として KRC や Miranda を使おうと述べている
KRC はよく知らないが、Miranda は Haskell に影響を与えた静的型付き関数型プログラミング言語である
Scheme や Lisp を使わずに SICP に似た本があるとすれば、それは SICP とはまったく違うものか、少なくとも同じことは教えられないだろう
経験上、Haskell と ML は Scheme よりはるかに理解しにくかったので、どの点が難しいのか気になる
先月読み始めたが、扱う範囲が広すぎると感じた
興味深い数学的原理をあまりにも多く駆け足で眺め、面白くなりかけたころに次のトピックへ移ってしまう
言い換えれば、浅すぎる
振り返ってみると、SICP から派生した講義や文書をすでに数多く見ていたため、トピックが紹介されるたびに「またこれか」と思ってしまったのも助けにならなかった
それでも無理やり最後までやってみたところ、Lisp を扱えるほど賢くなかったおかげで、むしろものすごく多くを学べた
コードを読むのにあまりにも多くの時間を費やしたおかげで、慣れた言語だったら学べたであろう以上のことを学んだ気がする
SICP の Python 版もある
自分で最後までやったわけでもなく、ざっと眺めた程度なので推薦ではないが、存在する証拠としてリンクを残しておく
https://wizardforcel.gitbooks.io/sicp-in-python/content/0.ht...
私の本棚でもこの2冊は並んで置かれており、間違いなく読む価値がある
2回目に読んだときは脚注と参考文献を掘り下げたが、そこにも美しい大きな世界があった
記憶が正しければ、Sussman とチームが天体の性質、つまり軌道を計算するためにカスタムのプログラマブルプロセッサを設計した論文がある
いつものことながら、頭がくらくらする内容である
SICP は、学部で限られた数のモデルしか学んでいなかった私に、プログラミングモデルには複数あるということを早い段階で理解させてくれた
どんな言語、ライブラリ、フレームワークのドキュメントを読んでも方向感覚をつかめそうだ、という感覚を与えてくれた本の一つだった
SICP の隣には、The Little * シリーズ全体も2回以上読む価値のある資料として置いている
Types and Programming Languages も良い
私の仕事には応用可能なコンピュータサイエンスだが、読むだけではだめで、実装もしなければならない
繰り返さないと一部を忘れてしまう
個人的にはその人を知っていて尊敬していたからかもしれないが、Dijkstra の本や論文はかなり頻繁に読み返す
今では直接適用するのは難しいが、頭には良いし、個人的には優れた書き手だと思う