実は・・・」といった自問自答の文章が延々と続くものだ。この本は、筆者と読者をひっくるめて「私たち」と表現している。これはこの本の独特の表記法であり、わざわざ、「なぜ私たちは私たちという表記を採用するに至ったか」という説明まで書いてある。Manualsそこまで書いている以上、翻訳でも「私たち」という表現を維持しなければならないのは当然の話だ。実際維持しているが、極めて日本語として不自然な文章になっている。このことから、私たちはとても重大な教訓を得た。文章は簡潔にすべし人間が読める文の量と速度は有限である。重要なのはプログラミングの仕方を教育することであって、文章の量ではない。これは文が悪文だったというものだ。次は技術的な悪書の理由について書く。サンプルコードの1割ほどがコンパイルできないコンパイルできない理由は、識別子が間違っているとか、あるべき記号が欠けているとか、極めて些細でお粗末なtypoがほとんどだ。このような問題は、本のソースコードからサンプルコードを抜き出してコンパイラーに通して文法違反がないかどうか確かめるテストを書けば防げる話だ。この本はわざわざ大量の文章を割いて、テストの重要性を説いている。Stroustrupには、「医者の不養生」というニッポンのコトワザを教えてあげたい。C++11の規格制定後に、C++11の新機能を使った行儀の良いお作法に対応させる修正を行っている。その過程で、「ふふん、この程度の変更は自明だからコンパイルして確認するまでもないね」という怠惰とうぬぼれがあったのだろう。テストを書くべきである。Stroustrupであろうと混乱したであろう興味深い間違いの例はある。conversionを防ぐなどのお作法のために、サンプルコードを全面的に修正したりしている。'a')というコードに対して盲目的に適用してしまったことだ。;理由は、brace-or-equal-initializerでは、まずstd::initializer_list<T>を引数に取るコンストラクターが探され、ない場合は、その他のコンストラクターで引数の数と型があるものが探される。std::stringには、initializer_list<char>を引数に取るコンストラクターがあるので、そちらが優先される。conversionとみなされない)。'a'}というリスト初期化だと解釈されてしまった。これはコンパイルも正常に通ってしまうので、実行して出力を確認しない限り見抜けないバグだ。ひとつの例は、C++03とC++11で挙動が変わるコードだ。ff;}can_open関数は、引数として与えられたファイル名でファイルを開けるかどうかを確認する関数だ。問題は、ffがファイルを開いているかどうかを、boolへの暗黙の型変換で調べている。bool()に変更された。そのため、C++11ではコンパイルエラーになる。そもそも、暗黙の型変換に頼るのが間違いなのだ。ファイルを開いているかどうか確認するメンバー関数is_open()があるのだから、それを使えばよい。これは、コンパイルさえしていれば発見できた問題だ。全体的には、極めてお粗末で些細なill-formedなサンプルコードばかりだ。テストは重要だ著者の文字コードへの理解がない本にはこう書いてある。「テキストファイルの最初の4バイトは4文字である」この文脈は、テキストファイル一般の話だ。これから扱う課題の入力に使うテキストファイルの最初の4バイトは常に4文字であるとみなすという仮定の話ではない。1文字は1バイトであると書いていることになる。二度と顔を出して表を歩けず、出版社の信頼は地に落ちることうけ合いだ。C++11にはUTF-8/UTF-16/UTF-32文字列リテラルが入っているのだからなおさら悪い。この文章は到底受け入れがたい。この本には、「中国の文字やマラヤーラム文字をサポートするには」などという文章も入っている。中国の文字やマラヤーラム文字をサポートした現実の文字コードは、すべて可変長エンコードであり、1文字は1バイトとは限らない。中国の文字やマラヤーラム文字をサポートするには、というのに続けて、C++の標準ライブラリのiostreamやlocaleの詳細な参考書を読むべきだとも書いている。iostreamやlocaleは、設計上可変長エンコードに対応できず、この文書は無責任である。ひどいことに、C++11で入った正規表現ライブラリもUnicodeに対応していると書いている。実際は対応していない。そもそも、可変上文字列に対応できない設計になっている。受け入れがたく無責任にもほどがある。Stroustrupに指摘したが、残念ながら話が噛み合わず、本人に修正を促すことはできなかった。曰く、「これは英語圏の話であるから」。英語圏とてUnicodeから逃れることはできないというのに。筆者の使う、unacceptableとかirresponsibleという言葉を侮辱的であると返すばかり。侮辱的にしろ、unacceptableなものはunacceptableであり、irresponsibleなものはirresponsibleでしかない。Windowsにおける文字コードの取り扱いなど、日本人プログラマーなら誰でも知っているし、Wikipediaなどで簡単に調べられることを、簡単に浅く説明した。筆者の専門ではない分野を扱ったのでマサカリが山と飛んでくることを恐れている。Cプリプロセッサーこの本のサンプルコードは、すべてstd_lib_facilities.hというヘッダーファイルを#includeすることが前提で書かれている。このヘッダーの中身は、本で使っている標準ライブラリヘッダーの#includeや、有益ないくつかの関数の追加。;などが書かれている。std;を書くのはよろしくないが、これが入門書だということを考えると、まだ納得もできる。納得のできないことはある。VectorCプリプロセッサーで、vectorというトークンをVectorに置き換えている。Vectorとは何か。以下のように定義されている。}};ようするに、operator[]でもat()を使った範囲外チェックを行うようにするものだ。本では、これを必要悪であり、現実のソフトウェアプロジェクトでもこのような技法を使うことはあり、実際に役に立っていると書いているが、とんでもないことだ。範囲外チェックを行いたければ、最初からat()を使っておけばいいのだ。fstreamを暗黙の型変換でboolに変換してファイルがオープンされているかどうか調べようとしたり、Stroustrupは大昔の粗野な時代の悪い癖が抜けていないのではないかと疑う。課題の設定この本では、まず冒頭で変数や関数、式、文など言語の文法の基本を教えたあと、次の章で練習課題を出している。この本は、まだプログラミング経験の一切ない初心者を対象にしていることを思い出してほしい。その上で、いま変数や関数やif文を覚えたばかりの初心者が、以下の課題を解く難易度を考えてほしい。実数と四則演算までならまだ初心者でもなんとかなるだろうが、括弧が出てきた時点で完全に初心者向けではない。この本では、まずBNF記法で数式の文法を定義したあと、教科書的な再帰下降構文解析による数式のパーサーを書いて計算を行っている。SICPでも冒頭でここまで無茶な課題はなかったはずだ。面白い課題であり、全プログラマーがプログラミング学習の比較的早い段階で一度は練習のために実装してみるべき課題ではあるが、いかにもタイミングが早すぎる。Stroustrupの本がここまで悪書だとは思わなかった。文字コードへの理解が致命的にない。Stroustrupのプログラミング入門の査読の仕事で、筆者は反面教師としての貴重な教訓を得た。C++11/14コア言語の執筆の経験からも、いろいろと執筆環境の不満点はあった。そこで、筆者が次に参考書を執筆するときは、以下のような環境で行おうと考えている。GNU/Linuxを使う。理由は、必要なソフトウェアが標準のパッケージマネージャーで揃う上、C++を書く上で圧倒的に快適だからだ。テキストディターにVimを使う。執筆環境はgitで管理する。Makeで参考書のビルドとテストを管理する。これ以上に複雑なビルドシステムは、参考書執筆では必要がないと判断した。参考書のソースコードはMarkdownで書く。HTMLなどの各種フォーマットへのコンパイルはpandocを使う。HTMLへの出力では、数式はmathjaxを使う。KaTexも興味深いので評価中だ。HTMLへの出力では、ソースコードはhighlight.jsを使ってシンタックスハイライトする。参考書のソースコードからサンプルコードを抽出してGCCとClangで文法チェックをする。textlintで日本語のチェックをする。できるだけ簡潔な文章を維持するために文章にこういったツールで制約をかける。これらのことをだいたい実装している。C++17の参考書を書くには不確定要素が多すぎるが、そろそろ準備は始めるべきだ。一つ不満なのが、textlintの実装がnode.jsで書かれていることだ。ツールとして使うのであるから、正しく動作さえすれば、どのような言語で書かれていようと気にしないのだが、結果的に、textlintの導入方法がなかなか厄介だった。Ubuntuにはnodejsパッケージがあるが、これはJavaScriptの実行環境が/usr/bin/nodejsというファイル名になっている。理由はすでにnodeというファイル名のパッケージが存在していて、名前が衝突するからだ。nodeパッケージをいれないのであれば、nodejs-legacyパッケージを入れることによって、/usr/bin/nodeへのsymlinkを貼れる。GitHubのレポジトリから直接/usr/localにファイルを引っ張ってくる。npmにより、パッケージ間の存関係が極めて複雑で、とても些細な機能ですらパッケージ化されている。ドワンゴ広告ドワンゴは1文字は1バイトではないとわかっている本物のC++プログラマーを募集しています。said...江添さんの本を楽しみにしています。今回執筆される本は、C++17に対応した初心者向けの本になるのでしょうか。said...『およそ悪書の見本』うっかり買ってしまう所でした。ご注意ありがとございます。ビョンビョンは昔から間違いが多いですが、周りを含めて誰もチェックできなかったの?といつも疑問です。"we"」を用いること自体は学術的な文章では極めて一般的ですよ。directly)」スタイルで書かれているそうなので、その意図に忠実に訳出するのは確かに苦労されたのかもしれません。said...文章量について。アメリカの教科書は簡潔なのを良しとせず、なぜそうなっているのかも含めて徹底的に細かく丁寧に説明するのが良書とされていると聞いたことがあります。私はその方が好きですね。(Atom)C++11参考書C++11の参考書、アマゾンお気に入りリストを公開中。アマゾンの江添のほしい物リストC++11の参考書、C++の文法と機能をGitHubで公開中。EvangelistC++標準化委員会の委員ドワンゴ社員C++11本を執筆した。株式会社ドワンゴで働いている。江添のほしい物リスト筆者にブログのネタを提供するために、直接に品物を送りたい場合、住所をメールで質問してください。Texts.ただし、必要である範囲において他の著作物を引用していることがあります。