腐った翻訳に対する態度について

今回、SICPの翻訳改訂版を公開するにあたって、minghai氏の非公式日本語版(以下、minghai氏版)については「惨憺たる翻訳」「そびえ立つクソの山」などと書きました。これらの言葉は、もちろん本心からのものです。しかし、それを表に出すかどうかについては、冷静に考えた結果として意図的に選択したことも確かです。ここでは、その背景について書こうと思います。

約一年前、私が善意のひどい訳についてという記事を書いたとき、しぶかわよしき様から以下のコメントをいただきました。

趣味のお金にならない翻訳だとだいたい最初の下訳で出しちゃいますね。だからといってそれが悪いことだとは思いません。英語を読まない人は言うまでもなく、英語を読める人でも「下訳」があれば原文を読む時にの速度は上がりますからね。クオリティに対して個人でできることといえば、指摘などで黙々と時間コストを代わりに負担するか、takeda25基金を作って、良い翻訳に対してパトロンになってお金を出すかどちらか以外はないと思います。このエントリーを読んでも世の中の品質があがることはなく、「翻訳するの怖い」と萎縮する人の方が多いと思います。ただでさえ、「怖いから」という話をよく聞きます。今は趣味翻訳する人もそれほど多くないけど、人数が増えれば、それだけ業界全体として翻訳にかける時間が増えて質も量も改善されると思います。僕は未熟でもなんでも、学生とかが翻訳をして公開するのが増えればいいと思ってます。

これに関して、四つのポイントから書いていきたいと思います。

  • ひどい翻訳はないほうがマシなのか
  • 腐った翻訳とはどのようなレベルか
  • 腐った翻訳を腐っていると言うべきか
  • 腐った翻訳を腐っていると言うことによる副作用とその対策

ひどい翻訳はないほうがマシなのか

情報は、基本的にはないよりもあったほうがいいものです。このことは直感的に共有されていると思います。

しかし、これは常に真であるとは限りません。例えば、次のような例を考えてみてください。日本語を片言レベルでしかわからない人が、何かの手違いで日本の首相にインタビューをすることになったとします。その人は、首相の言っていることがほとんど理解できず、たまたま知っていた単語を適当につなげて作文をしてしまった結果、荒唐無稽な記事が世に出てしまったとします。この場合、この記事が「ないほうがマシな情報」であることについてはあまり議論の余地がないでしょう。

ここで、情報が「ないほうがマシ」なものになってしまっているのは、その情報についての「メタ情報」(その情報がどのようなものであるかという情報)が間違っていることによります。どんな荒唐無稽なデタラメ記事であっても、「これは嘘ニュースです」と書かれて適切な場所で公開されていれば、ないほうがマシということにはなりません。上での例の記事が有害なのは、「首相の言葉」というラベルのもとで、首相の言葉でないものが公開されてしまっていることによるものです。

私がminghai氏版の翻訳を有害だと言っているのは、「SICP非公式日本語版」というラベルつきで、それに値しない情報が流されているからです。ついているラベルが「SICPに触発されて書いた自作ポエム」「SICP異世界語版」といったものであればよかったと思っています。

腐った翻訳とはどのようなレベルか

ここでは、「腐った翻訳」という言葉を「ないほうがマシというレベルの翻訳」という意味で使っていきます。

それでは、どのような翻訳が腐った翻訳なのでしょうか。一万文のテキストで、一万文すべてが誤訳であれば、それは確実に腐った翻訳でしょう。一方、一万文すべてが正確な翻訳であれば、確実に腐っていないと言えそうです。しかし、現実の翻訳は常にその間のどこかにあるものです。また、誤訳だらけの訳文から原文の意図を推測することが得意な人もいれば、それが苦手な人もいるでしょう。はっきりと「ここからが腐った翻訳だ」というクリアな線はありません。

私は、例えば2ページに1個程度の誤訳があれば、それは確実に腐った翻訳だと考えています。誤訳箇所に付箋をつけていくと見開きごとに貼っていくことになり、本が付箋でいっぱいになります。

minghai氏版には、大雑把にそのぐらいの誤訳があります。すべて指摘することはできませんが、ここではひとつだけ、翻訳の質を端的に示す例を挙げます。

In a related vein, an important current area in programming-language design is the exploration of so-called very high-level languages, in which one actually programs in terms of declarative statements.

関連領域において、プログラミング言語の設計における現在の重要な領域は超高水準言語と呼ばれる物の調査です。それは実際にプログラムを宣言的文の用語にて作成します。

ここで、"in terms of"を「の用語にて」と訳しています。英語が少しでもわかる人には、この誤訳がどのようなレベルのものかわかるでしょう。ほかにどのような誤訳があるか興味のある方は、真鍋版とminghai氏版と原文を見比べてみてください。

腐った翻訳を腐っていると言うべきか

私は、腐った翻訳についてはそのことをはっきり指摘するべきだと思っています。上で書いたように、腐った翻訳には現実的な害があるからです。指摘をしないで、どうやってその害を防ぐことができるのでしょうか。

英語が得意ではない人にとっては、翻訳が「腐っている」ということがどういうことなのかピンと来ないかもしれませんので、ここでプログラマ向けの例を出してみたいと思います。例えば、別言語からC言語に移植されたライブラリのコードを見ているところを想像してください。その途中、ある関数を見ていると、なんとその関数ではローカル変数へのポインタを返しているということに気づいてしまいます。C言語のまともなプログラマであれば、その瞬間にそのプログラムがどうしようもなく腐っていることに気がついてしまうでしょう。翻訳も同じようなものです。見た瞬間に、翻訳者が英語の文法も何もわかっていないことが気がついてしまうような誤訳というものがあるのです。

上での例のような腐ったコードがあれば、プログラマとしてはどうするべきでしょうか。まずは腐ったコードを「腐っている」と言い、そのコードをコンパイルしたプログラムを使わないように周知するべきではないでしょうか。それとも、初心者に「プログラミング怖い」という印象を持たれるかもしれないから言わないようにするべきでしょうか。私には、後者の意見は馬鹿げているように思えます。

腐った翻訳を腐っていると言うことによる副作用とその対策

以上のような理由から、私は腐っている翻訳には腐っていると言うべきだと考えていますが、それにはもちろん副作用が伴います。副作用には以下のようなものがあるでしょう。

  • 「翻訳するの怖い」と萎縮する人が出てくる
  • 無料の翻訳の量が減る
  • 言われた人が傷つく

それぞれについて考えてみます。

「翻訳するの怖い」と萎縮する人が出てくる

「腐った翻訳を出すと腐っていると言われるのが怖いから翻訳に手を出すのやめよう」という人が出てくるかもしれないということですが、それは「腐ったコードを公開すると腐っていると言われるのが怖いからプログラミングに手を出すのやめよう」というのと何が違うんでしょうか。

プログラミングと同じく、翻訳にもレベルがあります。プログラミング始めたばかりの人がLinuxカーネルにコントリビュートしようと思うでしょうか。それは無謀だと誰でもわかりますよね。最初は誰でも、自分なりの環境で単純な練習問題を解いたりするものです。翻訳もそれと同じです。自分の読めないレベルの文にいきなりぶつかるのではなく、自分に十分理解できるレベルの本を読むなどして実力を上げるのが結局は近道です。外国語なので、子供向けの本などを読むことも恥ずかしいことではありません。

「英語は苦手だけど翻訳に貢献したい」という気持ちは尊いかもしれませんが、まずは「英語が苦手」というのを克服してから貢献を考えてもいいと思います。それが間に合わなければ、自分で翻訳する代わりに、翻訳にかけるはずだった労力をアルバイトや残業などにつぎ込んで、それで得たお金でちゃんとした翻訳ができる人や会社に翻訳を頼むということもできるのではないでしょうか。

無料の翻訳の量が減る

「誰でも自由に趣味で翻訳するようになれば、無料の技術翻訳の量が増え、それに伴って質も上がるはず」という楽観的な意見があります。これはオープンソースソフトウェアのモデルが技術翻訳にもそのまま使えるんじゃないかという考え方から来ているのではないかと思います。しかし、ソフトウェア開発と技術翻訳はそんなに似ているのでしょうか。

実際のところ、技術翻訳は以下のような点でソフトウェア開発とは違います。

  • 創造性が少ない
  • 個人個人の速度の差が小さい
  • 再利用が利かない

まず、「創造性が少ない」という点について。プログラミングは、同じ目的を達成するのにも、非常に多くの選択肢があり、そこに創造性と楽しさが生まれます。翻訳は違います。翻訳は、あくまで原文の意図を忠実に伝えるということが第一です。文芸翻訳であれば創造性を発揮する余地もあるかもしれませんが、技術翻訳でそのような余地は限られています。

次に、「個人個人の速度の差が小さい」という点について。プログラミングであれば、一部の天才が数日間の突貫作業ですばらしいソフトウェアの基礎を作り上げるという話は珍しくありません。翻訳ではそのようなことはありません。どれだけ優れた翻訳者でも、平均的な翻訳者の何十倍もの速度で訳せるわけではありません。

最後に「再利用が利かない」という点について。ソフトウェアは、部品によって組み立てることができ、また作っているソフトウェア自身を部品として再利用しやすいようにすることができます。オープンソースソフトウェアは、まさにそのことによって驚くべき発展を成し遂げています。しかし、翻訳はそうではありません。一冊の本を翻訳しても、そこから再利用できるものはあまりありません。SICPの翻訳の一節がほかの本の一節として出てくるなんていうことはないのです(あるとしたら引用程度です)。翻訳メモリといった再利用の方法はありますが、同じ本の新しいバージョンでもない限り、あまり役に立つものではありません。

以上を総合すると、翻訳(特に技術翻訳)は「データを扱う」という共通点はあるものの、本質的にはソフトウェア開発よりも作業に近いと言えるでしょう。それは本来、対価が払われる仕事としてなされるべきものです。こういう面から考えても、無料の翻訳というものは時間やエネルギーに余裕がある人がボランティアとしてするぐらいのもので(現状ではそうなっていますよね)、安定的な供給が期待できるものではないのではないかと思います。

言われた人が傷つく

腐った翻訳をそうと自覚せずに公開した人に対して「翻訳が腐っている」と指摘すると、もちろん言われた人は傷つくことになるでしょう。いいことをしたと思っていた本人にとっては寝耳に水でしょうし、言うほうとしても気持ちのいいものではありません。

指摘をする場合には、「人身攻撃をしない」ということを心がける必要があります。私自身、minghai氏版の翻訳は腐っていると思いますし、それを公開したことは害悪だと思っていますが、それが善意から出た行動であることは疑っていません。不幸な事故のようなものだと思っています。

そもそも、なぜこういう不幸なことが起こってしまうのか。それを考えるほうが建設的ではないでしょうか。

私は、「翻訳とは誰にでもできる」という考えがその原因ではないかと思います。「翻訳は誰にでもできる」というのは、「注射は誰にでもできる」と言うようなものです。注射針を腕に突き立てることは誰にでもできますが、注射針を「正しく」刺すことは誰にでもできるわけではありません。翻訳もそれと同じです。自分がどの程度「正しく」翻訳できるかということを把握していないとひどいことになります。

まとめ

以上のように、私は「ないほうがマシなレベルの翻訳というものはある」「そのような翻訳に対してはそうと指摘するべきである」という考え方です。そして、minghai氏版の翻訳はそのようなレベルのものだと思っています。

本来は、minghai氏版を最初に見たときに指摘したかったところでした。当該記事のdara氏の次のコメントに強く共感します。

英語を「日本語」に変えるのは goo 翻訳でもやれます。ただ意味が通じない(何が言いたいかわからない)だけです。そして、それでは翻訳の意味がありません。

これを読み、私は言うべきことはすでに言われていると判断しました。minghai氏の回答は以下のようなものでした。

私はやれるだけのことをやりました。
後は皆さんの具体的な指摘を反映するか、または皆さんが私の成果の派生を好きに作って頂ければそれで満足です。

そのようなわけで、minghai氏に提供していただいたテンプレートをもとに、自分で翻訳を行いました。もちろん、テンプレートを提供していただいたことについては大変感謝しています。

私のこの翻訳により、SICPに興味を持つ人が増えることを願っているのはもちろんですが、「翻訳」ということについて真面目に考えてくれる人が増えてくれることも同時に願っています。

非公式PDF版SICP・新訳

計算機プログラムの構造と解釈、通称SICPを一から翻訳し直しました。


ファイル: SICP非公式日本語版 翻訳改訂版

リポジトリ: https://github.com/hiroshi-manabe/sicp-pdf


また、今回の翻訳をするにあたって考えたことを別記事にまとめました。


腐った翻訳に対する態度について


SICPはMITの有名なプログラミングの教科書です。詳しくはminghai氏の記事をご参照ください。

この翻訳改訂版は、minghai氏の非公式日本語版(以降、minghai氏版)のあまりにも惨憺たる翻訳を見かねて、原著から翻訳をし直したものです。この翻訳を進めるにあたっては、minghai氏版の訳を置き換えていくというやり方で進めていきました。しかし、差分を取ればわかっていただけると思いますが、minghai氏版のテキストは痕跡をとどめていないはずです。この方式を採ったのは、“そびえ立つクソの山”を少しずつ置き換えていくことによってやる気を出すという、主にモチベーション上の理由によるものです。もしminghai氏版の痕跡が(誰が訳しても同じようになるものを除いて)あるとすれば、それは作業漏れが残っているということですので、ご報告いただければ幸いです。

用語については、無用の混乱を避けるため、和田英一氏によるオンライン版「計算機プログラムの構造と解釈」(以下、和田氏版)にできるだけ追従するようにしました。もちろん、訳文はすべて自分で一から作り上げたものです。用語の追従によって著作権やライセンス上の問題が発生することはないと信じていますが、問題があるようであればお教えいただければと思います。

以下、minghai氏版に対して否定的なことを書くことになるため、人身攻撃をするつもりはない、また人身攻撃と受け取られるような部分があれば真剣に対応するということをあらかじめ表明しておきます。

minghai氏版を見たときの衝撃は、これまでにも何回も受けたことのある種類のものでした。ちょっと原文と比較するだけで、数限りなく致命的な誤訳が出てくる。またひとつ、とんでもない翻訳が世に出てしまった。なぜこういう悲劇はなくならないのか……。

私はそれまでにも SICP という本については聞いたことがあり、一度はしっかり読んでみたいと思っていたところでした。そこに出てきたminghai氏版がこのありさまだったため、書籍のほかにオンラインでも公開されている和田氏版に目を向けてみました。見ると、硬い印象の訳文で、すっと頭に入ってきにくいところはあるものの、真面目に時間をかけて読めば解読できるものでした。何より、(序文を除けば)致命的な誤訳は多くありません。それだけでも、minghai氏版よりはるかに優れていることは明らかでした。喩えるなら、和田氏版がこちこちに固くなった乾いたケーキだとすると、minghai氏版は柔らかい腐ったケーキというところでしょうか。

私としては、もしminghai氏版がなければ、和田氏版の訳書を購入して勉強して、それで済ませていたはずのところです。訳文は硬いとはいえ読めないことはなく、英語で読むよりは速く進められそうでした。ほかのこなれていない訳書同様、不満を持ちながら読み、それで終わりだったはずです。

しかし、minghai氏版が出てきたことで、状況は大きく変わりました。minghai氏版は無料のPDFなので、有料の書籍とオンラインHTMLという和田氏版よりアクセスが容易です。さらに、和田氏版は(Amazonのレビューにもあるように)翻訳の評判がよくありませんが、minghai氏版はですます調で一見親しみやすく、中身が腐っていることがすぐにはわかりません。

これでは、SICPの評判を聞いて勉強しようとした人が、minghai氏版に流れてしまうのではないか。私のその危惧は、Twitterのタイムラインで現実化していました。タイムラインでもminghai氏版に手を伸ばそうとしている人がいたため、和田氏版をお勧めしておきました。もちろん、その人は氷山の一角で、実際には少なからぬ人たちがminghai氏版に流れていることは確実でしょう。

文体が硬くて意味の取りにくい翻訳の場合、もたらす被害は限られています。訳文が直訳調で読みにくければ、読者はなんとか読み解く努力をするか、読むことをあきらめて訳者を責めるか(これはAmazonレビューで起こっていることです)のどちらかの行動を取るでしょう。後者の人に対しては(有料で購入した場合)金銭的な損害を与えているかもしれませんが、それがすべてです。どうしても読みにくければ、原文で読むことになるでしょう。いずれにせよ、翻訳が存在しなかった場合以上の害悪はありません。

しかし、表面上読みやすそうな腐った翻訳は、はるかに深刻な害悪をもたらす可能性があります。実際には誤訳のために訳文が意味不明になっているだけなのに、理解できないのは書いてある内容が難しすぎるためだ、それを理解するだけの頭脳が自分にないためだ、と読者は思い込んでしまうかもしれません。それだけはどうしても避けたいところです。

それらのことを考え合わせた結果、SICP を原文から翻訳しながら勉強していくことにしました。始めたとき、毎日一時間というペースで進めていくと決め、数日間やってみた進捗状況から翻訳が終わるまでの期間を見積もったところ、どうやら一年ぐらいかかりそうだとわかりました。一年というのは長い時間です。心がくじけそうになりつつも、ミヒャエル・エンデの「モモ」を思い出し、その日その日の分だけを考え、続けていきました。毎日夜9時からを定刻としていたため、Twitterでは「時報」と言ってくれる人もいました。

そして先日、ようやく翻訳とチェック作業が終わりました。期間は予定通り一年程度でした。勉強を兼ねての翻訳だったため、中身を理解しながら、練習問題もできるだけ(といっても、第3章の途中あたりでリタイアしましたが)解いていきました。前評判に違わず、SICPの内容はとても充実していました。翻訳前に危惧していたような、「この時間で何ができたか」と後悔するようなことにはならずにすみました。

もちろん、私のこの翻訳が完全だとは思っていません。しかし、致命的な誤訳が何百箇所もあってどこから手をつけていいかもわからないような“そびえ立つクソの山”でないことは保証します。この本の内容が理解できないとすれば、それは翻訳がおかしいからではありません。もちろん、内容が難しすぎるためでも、それを理解するだけの頭脳がないためでもありません。足りないのは時間をかけた読み込みです。じっくりと一文一文の意味を考え、サンプルコードを動かし、できるだけ練習問題を解いていけば、それで十分です。この本は、読者を置き去りにしようとするような本ではありません。

最後に、日本語版のテンプレートを提供していただいたことについて、minghai氏に深く感謝します。minghai氏の日本語版テンプレートがなければ、私のTeXLaTeXについての限られた知識では日本語訳を行うことはできなかったでしょう。

それでは、SICP非公式日本語版(真鍋版)をお楽しみください。

追記:PDF前文中の表現を改めました(編集前はこの記事とほぼ同じものを記載していました)。

「許す」と「赦す」の件(みんな間違っている)

シャルリー・エブド」誌の翻訳の問題がホットなようです。

私から見ると、みんな三者三様に間違っています

(最初に書いておきますが、ここでは主に日本語表記について述べ、シャルリー・エブド誌の表紙という本題にはあまり触れません)

関口涼子氏の間違い

まず、関口涼子氏の間違いから。

Tout est pardonnéを、「すべては許される」とすることで、この読みの多様性が全て消えてしまう。


もうすでにあちこちで指摘されていますが、「許す」は「赦す」を含んでいます。

現代日本語で「許す」と「赦す」が排他的に使い分けられているなんていうことはありません。


で、こういうときには必ず、常用漢字(当用漢字)云々という人が出てきますが、それも誤解です。

そういう人の頭の中では、戦前の日本語は失われたエル・ドラド的なもので、その世界ではすべての書き分けが正しく(「正しく」とは?)行われていたというイメージなのかもしれませんが、全くそんなことはありません。


「ゆるす」に関して言うと、「許す」は昔から "pardonner(pardon)" の意味でも "permettre*1(permit)" の意味でも使われてきています。*2

本を読んでいれば当然わかることですが、そうでなくてもちょっと調べればわかることです。


例えば、菊池寛の訳した「后デルヴオルギラ(オーガスタ・グレゴリー)」に次のような部分があります。


文藝春秋


もし書き分けが昔からされていたとしたら、ここは「赦す」を使っているはずのところです。

じゃあなぜ「許す」が使われているか。

単純に、明確な使い分けがなかったからです。


青空文庫で検索してみれば、このような用法はいくらでも見つかります。

もし私が亡友に対すると同じような善良な心で、妻の前に懺悔ざんげの言葉を並べたなら、妻はうれし涙をこぼしても私の罪を許してくれたに違いないのです。

こころ(夏目漱石)

龍王、聖龍王。わたしの罪を許しわたくしの呪をお解きください。

龍と詩人(宮澤賢治)

ああ、許し給へ。どんなまづしい作家でも、おのれの小説の主人公をひそかに神へ近づけたがつてゐるものだ。

道化の華(太宰治)

「それを半分だけ上げますから早く私を許して下さい」

ツクツク法師(夢野久作)


関口涼子という人がどれほどのものかは知りませんが、これらは全部間違っているとでも言うのか、それともこれらは全部 permettre の意味だとでも言うのでしょうか。


それに、彼女自身が「許す」を pardonner の意味で使っているんですよね。

長い間の不和があり、それは実際には忘れられることも、許されることも出来ないかもしれない。


これは permettre では意味が通りません。

自分から、「許す」を(日本語の伝統に基づいて、正しく)pardonner の意味で使っているということです。

語るに落ちるではないですが、「書くに落ちる」とでもいうところでしょうか。


念のために付け加えると、「ゆるす」はほかの和語同様に昔から多様な表記があり、その中にはもちろん「赦す」も含まれていて、あえてその字を使う場合には「罪をゆるす」という意味で使われているというのは確かです。

しかし、「許す」との明確な使い分けが成立していた時代なんていうものはありません。

それは現代でも同じです。

「許す」が pardonner の意味で使われているから、「絶許(絶対に許さない)」のようなものがあるわけです。

(それとも、これも「絶赦」と書けとでも言うのでしょうか)


こういうわけで、関口氏が "Tout est pardonné" の訳にあえて「赦す」を使うのは自由ですが、「すべては許される」と訳したのを誤訳だというなら、それは間違いです。

しかし、じゃあ読売新聞には何の問題もないのかというと、それはまったく別の問題です。

読売新聞の間違い

"Tout est pardonné" を解釈するには、訳文ではなく原文のニュアンスを取る必要があります。

翻訳では、原文のニュアンスがどうやっても失われるものです。

原語がわからない人が、「すべては許される」という訳文から勝手に意味を取ってはいけません。

訳文にどの漢字を使ったら OK という問題ではありません。


いい例はないかと探してみたら、次のようなものがありました。

"Qui a éteint le soleil ?"


この絵本のタイトルは "Qui a éteint le soleil ?" ですが、これは直訳すると「誰が太陽を消したのか?」となります。

しかし、この「誰が太陽を消したのか?」という訳文から、「著者は太陽が消滅した世界を描くことで…」のようなことを書いてしまうと、とんでもない見当違いになってしまいます。

というのは、"éteindre" は「火・電灯などを消す」という意味であって、「消滅させる」ではないからです。

この場合、日本語ではどう頑張っても「消す」としか書けないので、原語を表記に反映させることはできません。


しかし、それは「誰が太陽を消したのか?」が誤訳ということではありません。

突き詰めると、すべての翻訳は誤訳であるということになってしまいます。

(それは一面の真実ではあるのですが)


元々、外国語の意味を正確に移すなんていうことは、平仮名で書こうが漢字で書こうが不可能です。

ですので、読売新聞の間違いは「すべては許される」と訳した段階ではなく、その訳文からニュアンスを推測したという段階です。

原文の表現について何かを言うためには原語の知識が必要だという、ごく当たり前のことです。*3

id:yuki_chikaさんの間違い

「許す」と「赦す」は同じ意味ですよというタイトルですが、これはもちろん間違いです。


私個人としては高島俊男先生のファンですし、面倒な書き分けを増やすのにも反対で、なぜ広まった? 「『訊く』が正しい」という迷信という記事を書いたぐらいですが、書き分けをしている人にはその人なりの意図があるというのが当然です。

私が反対しているのは、「ask の意味では必ず『訊く』と書くべきだ」というような、これまで存在したことのない厄介なルールを導入することであって、「訊く」を ask の意味で使うことは止めていません(というより、止められません)。


同様に、「pardonner の意味では必ず『赦す』と書くべきだ」なんてバカらしい主張には反対だというのが私の意見ですが、「赦す」と書く人は permettre ではなく pardonner という意味に限定しようとして使っているというのはあまり争いのない事実でしょう。

意見と事実は分ける必要があります。


高島先生の意見を敷衍すると、日本語の「ゆるす」は pardonner と permettre にわたる*4広い意味を持っているので、書き分ける必要はなく、平仮名で書くか、漢字で書くにしても「許す」という代表的な表記ですべて表すようにしたほうがいいということになるでしょう。

実際、高島俊男先生ご本人はあらゆる和語の書き分けに反対している(「取る」「採る」「捕る」「撮る」などを書き分けず、「とる」または「取る」と書く)ので一貫性はあるのですが、普通はそこまで振り切ることはできません。

現に、id:yuki_chika さんも「採る」という表記は使っています。

私は別に反知性主義を採るものではない。

「『ググレカス』が世界を変える」…のか? 自由と情報をめぐる議論


これは使い方としてはごく普通ですし、揚げ足取りが目的ではありません。

言いたいのは、高島先生のような強烈なキャラクタの人間でもなければ、現代に生きて日本語を使う以上、誰でもある程度の和語の書き分けはせざるを得ないということ、そして書き分けをする以上は「何を書き分けて何を書き分けないか」ということは難しい問題とならざるを得ないということです。

まとめ
  • 読売新聞は、訳文から原文のニュアンスを推測するという間違いを犯しています。
  • 関口涼子氏は、「すべては許される」を誤訳とするという間違いを犯しています(「すべては許される」という訳文を誤読している、と書けば間違いのないところです)。
  • id:yuki_chikaさんは、「和語は書き分けるべきではない」という「意見」と、「和語の書き分けに意味はない」という「事実」を混同しています。


個人的には、シャルリー・エブドの真の意図についてはフランス語のわかる各個人が個別に判断すればいいことで、あまり意見はありません。

しかし、そこから派生した「ゆるす」の表記問題については黙っているわけにはいきません。

「今後この使い分けをしていこう」というならまだしも(もちろん私は個人的な意見として反対しますが)、「これまでにこういう使い分けがされている」という主張であれば、それは明確なです。

ちょっと考えれば、これまでの日本語で、例えば「いくら謝っても赦してくれないんだよ」みたいな気持ち悪い書き方はほとんど見たことがないということぐらい、誰でもわかるはずのところです。


それにしても、予想できることですが、「許す」と「赦す」の書き分けが成立していると(事実に反して)思い込んでいる人が大量に湧いています。

上に挙げた夏目漱石太宰治すらろくに読んでもいないくせに(あるいは、読んでも一瞬で忘れて)、ネットでそれっぽい漢字の書き分けを見ると1000年前から知っていたような顔をして得意げに書き込む頭の軽い人間ばかりのようです。

しかし、数からいうとそういう頭の軽い人間が圧倒的多数派でしょうし、今後それっぽい漢字の書き分けがどんどん増えていくのは、憂鬱ですが避けられないところかもしれません。


最近では、「笑う/嗤う」みたいな書き分けも頭の軽い人たちの間でかなり定着してきているみたいですし、次に出てくる新しい書き分け(個人的には「助ける/救ける/援ける…」あたりが来そうな気がしています)を1000年前から知っていたような顔をする準備をしておいたほうがいいかもしれないですね。

(まあ、そういう人は自然にそうしていると思いますが)


最後に、とってつけたように最近読んだ本へのアフィリエイトリンクを貼っておきます。


*1:指摘を受けて修正しました。

*2:"excuser(excuse)" というものもありますが、関口氏の話に出てきていないので省略します。

*3:しかし、pardonnéだからといって、“ムハンマドの風刺も「表現の自由」の枠内との見解を訴えたとみられる。” とは決して言えないかというと、そこは微妙なところだと思います。

*4:これは単純化で、「ゆるす」全体の意味はこれらに限定されるものではありません。

なぜ誤訳指摘をしたか

善意のひどい訳についてについての補足を書く。


まず、「なぜ指摘を公開でやったのか」ということから。

「アスペ日記」というタイトルで日記を書いてはいるけれど、「こんなふうに誤訳指摘したら気ぃ悪い(感じ悪い)*1よなぁ」ぐらいの感覚はぼくにもあった。

じゃあ、なぜそうしたか。

その理由を箇条書きしてみる。

この記事を書くことで、id:ymotongpoo さんの傷口に塩を塗るようなことになるかもしれないけれど、許してもらえればと思う。

1. 翻訳記事の読み方について考えるきっかけになると思った。

元記事は、ぼくが最初に見たときは100ブクマも行っていなかったと思うけれど、みるみるうちに伸びて、300ブクマを超えた。

あれだけ誤訳の多い記事が、ただ漫然と消費される様子に疑問を持った。

日本語だけ読んでもおかしなところがある(指摘箇所を見てもらえばわかると思う)翻訳なのに、みんな適当に目を滑らせて、何となくわかったつもりになって、それでいいのか?

誤訳を指摘することで、それに一石を投じてみたかった。

2. 体感英語力と翻訳の実力に乖離があると思った。

記事を見たあとで id:ymotongpoo さんについて調べてみると、東京大学修士課程を修了し、Google で働いているらしいということがわかった。

ということは、英語の論文もそれなりに読んでいるだろうし、仕事でも毎日英語を使っているだろう。

そうなると、本人の体感英語力は相当高いだろう。

しかし、翻訳は明らかに誤訳が多い。

「英語を使って生きていく能力」と「英語を間違えずに解釈する能力」は別なんだろう。

これは気づきにくいことで、ぼくもあまり意識していなかった。

そのことについて書こうと考えていた(が、結果として元記事ではそこまで書けていない。推敲が足りなかった)。

3. 翻訳はコンパイルエラーのような形で誤訳がわからないから。

コードであれば、書いた内容に間違いがあれば、コンパイルエラーといった形でそれがすぐにわかる。

しかし、翻訳の場合、訳し間違いがあっても本人にはわからない。

だから、本人にわかる形でフィードバックをしようと思った。

これだけでは公開でやる理由にはならないが、4以降で補足する。

4. 公開で指摘することで、ほかの人の参考にもなると思った。

どういうところで間違えているかというのは、当然ほかの人の参考にもなるはずだ。

実際、ブコメで参考になると言ってくれている人もいた。

5. 誤訳箇所があまりにも多かったから。

これを最後に持ってくるのは本当に感じ悪いとは思うけれど、嘘をつくよりは実際のところを書く。

誤訳を指摘しようと思ったのは 4 までの理由だが、この誤訳密度で修正箇所を訳し直すと、原文の相当な割合を翻訳することになる。

それなら、ぶつ切れで翻訳するより、全体をいったん自分のバージョンとして訳し直したほうが楽だ。

それと突き合わせて誤訳を指摘することにした。

さて、そうなると訳し直したバージョンがもったいない。

日本語としてこなれてはいなくても、内容を理解して読めるものにはなっているはずだ。

それを公開することで、誰かの役に立つかもしれない。

この動機は、id:ymotongpoo さんが最初に公開された動機と同じだろう。

しかし、id:ymotongpoo さんを傷つけないということと、訳し直したバージョンを公開するということはどうしても両立しない。

それで、申し訳ないが後者を優先した。

それがアスペ的だと言われたらそうかもしれない。

言葉遣いについても配慮が足りなかったかもしれず、申し訳ない。


ところで、ぼくは「完璧な翻訳でなければ公開するな」とは言っていない。

ぼくだって完璧な翻訳なんてできない。

でも、5ページ(PDF版)の文章に(修正箇所を含めると)32箇所の誤訳というのはちょっと多いんじゃないかと思った。

普段から、(引き合いに出して申し訳ないが)江添氏の翻訳などは読んでいるが、そこまでのことは普通はない。


ところで、この件に関しては非常に不愉快なことがあった。



へぇぇ。

このタイミングで言うんですか。

「この人達」って、id:ymotongpoo さんとはつながってるんだから、その前に記事がバズってたときにいくらでも言う機会があったと思うんですけどねぇぇぇ。

これが、アスペでない人間にはあるという雰囲気を読む能力ですか。

いやぁ、ついていけないっすわ。

(吐瀉音)



>原著者の意向を歪める事を極力避けたいことを強調されるこのブログの方は

>原著者の意向を歪める事を極力避けたいことを強調されるこのブログの方は

>原著者の意向を歪める事を極力避けたいことを強調されるこのブログの方は


すごい!!!

こう書けば、仲間は非難せずにぼくだけを倫理的に非難できると。

高等技っすねぇ。

(吐瀉音)


ぼくは確かに雰囲気を読む能力が欠けているところがあるので、日常生活での行動は周りの常人を見習ってやっている。

道路標識に50キロ制限と書いてあっても、周りの車が時速70キロで走っていたら時速70キロで走る。

そんな感じだ。


例の記事も、かなり古い伝説的な文書で、元記事の人が何も書かずに翻訳していて、300ブクマぐらいの間誰にもツッコミを入れられていないので、あぁ人間的にはこれはオッケーなのかなと思ってぼくもそのまま公開した。

いやぁ、しかしまさかぼくだけ倫理的に非難する裏技があったとは。

そこまでは思いつかなかったなぁ。


で、調べてみるとこのファイルはPlan 9のソースに含まれているようで、Lucent Public License version 1.02 が適用されるようだった。

一応追記しておいた


id:ymotongpoo さんも追記しておいたほうがいいかもしれないですね。

いやぁ、ゴミが同じことをしたせいで手間をかけさせて申し訳ないですね。

*1:関西に住むうちに中途半端に関西弁がうつった。

善意のひどい訳について

2014/10/14 追記: 補足記事を書きました。なぜ誤訳指摘をしたか


ぼくは、ずっと昔から「ひどい翻訳」というものに憤りを感じてきた。

以前、別の記事に書いたこともある。

統計学を拓いた異才たちのようなひどい翻訳を見るたびに、どうして世の中からはこの手の悲劇がなくならないのかとため息が出る。


この前、またひどい翻訳を目にする機会があった。

C言語でプログラミングする際の覚書


ちょっと原文と比較すると致命的な誤訳がいくつも見つかる、最低クラスの翻訳だ。

やれやれと思いながら、翻訳のひどさを嘆くコメントをはてブに残して、ツイッターに流した。



日常の一コマだ。


ここでちょっといつもと違う流れになったのは、訳者の方からリプライをもらったということ。



そういえば今はネット時代なんだから、誤訳指摘が訳者の目にもとまるというのは十分ありうることだ。


その後リプライを通して、誤訳を 2箇所直してもらった。

普通の流れなら、ここで一件落着、みんなハッピーというところだ。


でも違う、そうじゃない。

誤訳は 2箇所 どころじゃない。

ちゃんと指摘すると、何箇所になるかわからないぐらいあるんだ。


統計学を拓いた異才たちを読んだとき、あまりに翻訳がひどいので原書(おすすめです)を買って読んで、和訳の誤訳箇所に付箋を貼ろうとしたことがある。

しかし、最初の数ページまで見たところで付箋だらけになってしまい、不毛な気持ちになってあきらめた。


でも今回は、量が少ないこともあるので、「誤訳の全指摘」をやってみることにした。

ひどい翻訳というものにはどれだけの誤訳があるものかを示したかったし、自分でも興味があった。


自分でも全文を翻訳してみて、それと比べながら指摘箇所をまとめた。

すると、誤訳は(指摘済みの2箇所のほかに)30箇所あった。


誤訳指摘は別記事にまとめた。

「C言語でプログラミングする際の覚書」の誤訳箇所


ちなみに、ぼくの参考訳はこちら。

C言語プログラミングの覚え書き(改訳)


今回の件で、ひどい翻訳というものについて真剣に考えることになった。

これまで、ひどい翻訳を見ると、無意識のうちにそれを何らかのモラルの欠如によるものだと思っていた。

ろくに英語を勉強していない人が身の程知らずに翻訳しているか、手抜きで翻訳を見直しもしないとか。

だから、ひどい翻訳を見るといつも怒りを感じていた。

しかし、今回の翻訳を出した id:ymotongpooさんは明らかに紳士的な人で、人間としても技術者としてもすばらしい人のようだった。

ツイッターで話してみると真面目に考えて訳されたようで、調べてみると外資系企業で普段から英語を使って仕事をされているらしい。*1

マニュアルの翻訳や書籍の翻訳もされているようだ。


でも、背景はともかく、例の翻訳はあまりにもひどい。

コードの質が、誰が書いたかではなくどう書かれているかで判断されるように、翻訳の質も、誰が訳したかではなくどう訳されているかで判断するべきだと思う。


例の翻訳も、ぼくの翻訳も、さらっと読んだ感じの印象はあまり変わらないかもしれない。

翻訳の質というのは、それほど重要じゃないのかもしれない。

それでもぼくは、誤訳の多い翻訳はよくないと思っている。

理由は主に二つ。

  1. 文章をきちんと読むという習慣を阻害する。
  2. 著作物のアイデンティティの問題。


一つ目の「文章をきちんと読むという習慣を阻害する」というのは、そういう誤訳だらけの文章を読んでいると、一字一句をちゃんと理解して読もうとするとつまずいてしまうからだ。

例えば、元の翻訳の次の部分。

if(goleft)
     p->left=p->right->left;
else
     p->right=p->left->right;

p の複合的な使い方をしているこのコードが何をしているかを考えてみましょう。

ここでの「このコード」はただの例だ。

「何をしているか」を考えてもしょうがない。

でも、「きちんと読む」ということをしようとしてしまうと、ここで引っかかってしまう。

ちなみに、ぼくの翻訳は次のようなものだ。

次のコードで、もし p の代わりに複合式を使っていたらどんな見た目になるか考えてみてください。


二つ目の「著作物のアイデンティティの問題」というのは、「その訳文は、そのタイトルに値するのか?」ということ。

統計学を拓いた異才たち」を読んだ人は、"The Lady Tasting Tea"と同じ本を読んだと言えるのか?

C言語でプログラミングする際の覚書」を読んだ人は、"Notes on Programming in C"を読んだと言えるのか?

どちらも、訳文の意味の通らないところを読んで、読者が「この著者の書く文章はわかりにくいな」と思ってしまうかもしれない。

ひどい翻訳というのは、機械翻訳よりはずっとましかもしれないが、そういう点で危険だ。

機械翻訳なら、原著者がわかりにくいことを書いたとは思わないだろう。


いろいろ悪く書いたけれど、それはあくまで訳文に対するもので、人格攻撃ではない。

翻訳というシステムがもっとうまく動くようになってくれればいいと願っている。

原文を読めばいいと言う人もいるかもしれないが、外国語を読むのには時間がかかる。

ぼくは速いほうだとは自負しているけれど、それでも日本語に比べるとだいぶ遅くなる。


技術翻訳は残念なものが多いが、文芸翻訳は平均して質が高いと感じる。

翻訳で読んだ本には、すばらしいものがいくつもある。

ここではお気に入りを二つ挙げる。



どちらも翻訳でも原文でも読んだけれど、誤訳はほとんどなかった。*2

何百ページもある本をほとんど誤訳なしに訳すのだから、考えてみるとすごいことだ。


技術翻訳も、専業の翻訳者との連携でできたらいいんじゃないかと思う。

専門知識のない翻訳者でも、技術文書の翻訳で助けになれるところは多いはずだ。

例えば、

a naming convention from which np means ``node pointer'' is easily derived.

の "which" が関係代名詞であること、

parsing tables, which encode the grammar of a programming language

の "parsing tables" が動詞-目的語構造ではなく全体でひとつの名詞句であることを読み取るのに、プログラミングの知識は必要ない。

それは英語自体から読み取れる。


英語(外国語)の構文を間違えずに読むというのは、ひとつの能力だ。

翻訳には、分野の専門知識と同じぐらい、外国語を読む能力が必要だ。

(その能力のない)技術者が単独で翻訳をすると、分野の専門知識を何も知らない翻訳者が単独で翻訳するのと同じぐらい悲惨なことになる。

しかし、専門知識のない翻訳者が単独で技術書を翻訳することはあまりないのに、英語(外国語)の読めない技術者が単独で技術書を翻訳するというのは、ずっとよくあることだ。

「翻訳」ということの本質的な困難さが認識されて、後者が前者と同じぐらいひどいことだという認識が広まってほしいと思っている。


ところで、id:ymotongpoo さんが「すごいErlangゆかいに学ぼう!」を翻訳されたときはGitHubのプライベートリポジトリなどでされたそうだ。



この書籍はまだ拝見していないが(そのうち読んでみたい)、多くのレビュアーによって質の高いものになっていることと思う。

こういう体制が普及していけば、例えば専業翻訳家との連携のようなこともやりやすくなって、統計学を拓いた異才たちのような「英語の読めない専門家によるひどい翻訳がそのまま書籍になってしまう」という悲劇が起こらなくなるんじゃないかと期待している。


後記1 この記事の中では「統計学を拓いた異才たち」を非常に悪く言っているが、この訳書はそれに値するものだと思っている。仕事になるのであれば、その数百箇所にのぼるであろう誤訳を全指摘したいところだ。

後記2 「じゃあお前は何を翻訳したんだ」と言われるかもしれない。ぼくはこれまで翻訳はあまりしていない。そのことはこの記事の主張とは関係ないと思うが、いま少しずつ手をつけているものはある。公開できるところまで行ければいいと思う。

*1:エンジニアとして有名な方のようだが、ぼくはアンテナが低いせいか知らなかった。

*2:突き合わせて読んだわけではないけれど、大きな誤訳があれば読めばわかる。

「C言語でプログラミングする際の覚書」の誤訳箇所

ここでは、C言語でプログラミングする際の覚書の誤訳を列挙します。

参考として、私の翻訳はC言語プログラミングの覚え書き(改訳)にあります。

What follows is ...

×従うべきは

○これから述べるのは

"What follows" で「続くもの」という意味です。ここでの「続く」というのは、現在の文章に続く、つまり「以下に述べること」です。

But they've been accumulating in my head, if not on paper until now, for a long time, ...

×しかし、私の意見は頭のなかにしばらくあったものをまとめたものであり、長らく文章として公開してきませんでした。

○しかし、これらのことは、文書として書いたことはありませんでしたが、私の頭の中に長い時間をかけて蓄積してきたもので、…

"if not on paper until now" これは、"in my head" との対比です。「頭の中にはあったが、文書にしたことはない」という意味です。また、"for a long time" は "they've been accumulating in my head" にかかります。

I've yet to see a good essay on how to plan the whole thing,

×これまでプログラム全体の計画に関しての良い文章は読んだことがありますが、

○全体を計画する方法についてのよいエッセイを読んだことはありませんが、

"yet to" は「まだ…していない」という意味です。文意が完全に逆になっています。

a clear program is not made any clearer by such presentation

×明瞭なプログラムはそのような見た目で成されるものではなく

○明瞭なプログラムはそんな表示をしてもそれ以上明瞭にはなりませんし

"not made any clearer" は「さらに明瞭にはならない」ということです。

... is more to type (or calls upon your text editor)

×タイプ量(あるいはエディタ内で呼ばれる回数)が増え

○タイプ量が増える(または、エディタの助けを求める)ことになりますし

"call (up)on" は「頼る」という意味です。

if you consistently use a naming convention from which np means ``node pointer'' is easily derived

×どの np が "node pointer" を意味しているかがすぐに分かる命名規則を一貫して使っていれば

○np が "node pointer" を指しているということが簡単に導けるような命名規約を一貫して使っていれば

"from which" の "which" は "naming convention" を指しています。

As in all other aspects of readable programming, consistency is important in naming.

×プログラムの可読性に関していえば、命名において一貫性は重要です。

○プログラムの可読性に関するほかの側面での場合と同じように、命名においても一貫性は重要です。

元の翻訳では "As in all other aspects" が訳されていません。

I prefer minimum-length but maximum-information names

×私は最短の名前ではなく最も情報量がある名前を好み

○私は最短の長さで最大の情報量のある名前を好み

「最短であるが、しかし最大の情報量を持つ」という意味です。

They jangle like bad typography.

×悪い印刷のように目障りなのです。

○ひどい表示の仕方と同じように目障りなのです。

最初は、全篇を通して "typography" が「印刷」と訳されていたと思うのですが、その名残でしょうか。

Pointers are sharp tools

×ポインタは賢い道具で

○ポインタは切れ味の鋭い道具で

文字通りの意味です。「賢い」では、あとの「使い方を間違えると…」とつながりません。

If we want the next element's type

×もし次の要素の型が必要な場合は

○もし次の要素の type が必要であれば

原文で type がコード用フォントになっていませんが、文脈から構造体の要素名であることが明らかです。

less effort is expended by the compiler and computer

×コンパイラやコンピュータが展開する労力も減ります

コンパイラやコンピュータの費やす労力も減ります

"expend"(費やす)を "expand"(展開する)と間違えたのでしょう。

which allows some helpful compile-time error checking that array indices cannot share

×これでコンパイル時に配列のインデックスが適切で無い旨のエラー検出が可能になります。

○配列の添字と違ってコンパイル時の便利なエラー検出が利用できます。

"array indices cannot share" の "share" は、「同じく持つ」という意味です。配列の添字ではエラー検出ができないということです。意味が取れておらず、つじつま合わせになっています。

As a rule

×ルールとして

○だいたいの場合

熟語です。

expressions that evaluate to elements of a data structure

×データ構造の要素を評価するような…データ構造

○データ構造の要素として評価される式

ここでの "evaluate to" は、「評価されることによって…になる」という意味です。

Consider what ... would look like using a compound expression for p

×p の複合的な使い方をしているこのコードが何をしているかを考えてみましょう

○もし p の代わりに複合式を使っていたらどんな見た目になるか考えてみてください

「p の代わりに複合式(例えば、node[i] など)を使ったらゴチャゴチャした見た目になる」ということです。元の訳では意味不明です。

Sometimes it's worth a temporary variable (here p) or a macro to distill the calculation.

×時には一時変数(この場合は p )を使用したり、計算の本質を抜き出すマクロを使用する価値があります。

○計算の本質を抜き出すには、時には一時変数(ここでは p)やマクロを使うことが役に立ちます。

「一時変数」と「マクロ」は並列です。

Procedure names should reflect what they do; function names should reflect what they return.

×プロシージャ名はそれが何をするかを反映すべきです。つまり関数名はそれが何を返すかを反映すべきです。

○プロシージャ名は、それが何をするかを表しているべきです。関数名は、それが何を返すかを表しているべきです。

原文にない「つまり」があるために、実際にはない論理的関係があるかのように見えてしまいます。

A delicate matter, requiring taste and judgement.

×慎重に、経験と判断をもって書く必要があります。

○これはセンスと判断力が必要となる難しい問題です。

コメントの「書き方」ではなく、「コメントを書くこと(書くかどうかを含め)」全体に対するものです。

a symbol table might be implemented ...

×シンボルテーブルは…として実装されているでしょう

○シンボルテーブルは…として実装されるかもしれません

"might" はかなり弱い意味です。

Algorithms, or details of algorithms, can often be encoded compactly, efficiently and expressively as data rather than, say, as lots of if statements.

×アルゴリズム、つまりアルゴリズムの細かな部分は、しばしばデータという簡潔で、効率的で、表現豊かな形に記号化されます。それは、たとえば、多くのif文という形ではありません。

アルゴリズムや、アルゴリズムの細かいところは、たくさんの if 文のようなもので書くよりも、データとして書いたほうが、効率よく強力に記号化することができることがよくあります。

元の訳は、日本語としてよくわからないものになっています。

A classic example of this is parsing tables, which encode the grammar of a programming language in a form interpretable by a fixed, fairly simple piece of code.

×古典的な例で言えば、表のパースです。これはプログラミング言語の文法を、定形のかなり単純なコード片によって説明可能な形式に記号化することです。

○典型的な例としては、パージングテーブルというものがあります。プログラミング言語の文法を、定型のかなり単純なコードによって解釈できる形に記号化したものです。

"parsing tables" は全体でひとつの名詞です。動詞-目的語ではありません。また、"interpretable" はコードによって「解釈」できる、つまり読み込んでそれに従って動作できるという意味で、「説明」ではありません。

Finite state machines are particularly amenable to this form of attack

×特にこのような問題に取り組むときには有限状態機械が採用されていますが

○この手のやり方としては有限状態機械が特に柔軟に使えますが

"amenable" は「従順な」、つまり「柔軟に使いやすい」ということです。

can be constructed profitably as a data-driven algorithm

×生産的な形としてデータ駆動のアルゴリズムになります

○データ駆動アルゴリズムにすることでいい結果が得られるでしょう

"profitably" は、「利益が得られるような形で」というニュアンスです。

One of the reasons data-driven programs are not common, at least among beginners, is the tyranny of Pascal.

×データ駆動プログラムが一般的でない理由の一つは、少なくとも初心者においては、Pascalによる圧政でしょう。

○データ駆動プログラムが(少なくとも初心者の間で)一般的でない理由のひとつは、Pascalの独裁です。

"at least among beginners" は前にかかります。

This flies in the face of the theories of Turing and von Neumann

×このことはチューリングフォン・ノイマンの理論の前にはたち消えてしまいます

○これはチューリングフォン・ノイマンの理論に真っ向から喧嘩を売っています

"fly in the face of" は「真っ向から対立する」です。これは私も調べたところなのですが、「ここはたぶん熟語じゃないか」というセンスが必要です。適当に訳をでっち上げるのはよくありません。

I cannot recommend an implementation style more highly

×より高度な次元の実装方法を推奨することはできません

○これほどお勧めできる実装スタイルはありません

"highly recommend" という組み合わせはよく聞くものですが、"recommend ... more highly" はその比較級です。「それ以上お勧めできない」、つまり「とてもお勧めできる」ということです。

Maybe that's it:

×以上です。

○きっとこういうことなのでしょう。

これは ":" に続くものに対しての文です。

by construction

×ビルド時に

○組み立て方によって

「組み立て方を工夫することで(多重インクルードを避けられる)」程度の意味です。

but it's usually done wrong in practice

×普通は間違った結果となります

○実際には正しく運用されないものです

"in practice" 実際にやってみると、"done wrong" 悪いやり方で行われる、という意味です。元の訳ではなぜ「間違った結果」になるのかわかりません。

C言語プログラミングの覚え書き(改訳)

原文: Notes on Programming in C

Rob Pike

1989年2月21日

Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights Reserved.

Lucent Public License Version 1.02

前書き

KernighanとPlaugerによる“The Elements of Programming Style” (「プログラム書法」木村泉訳)は重要で影響力のある本です。この本にはそれだけの価値があります。しかし、その中の簡潔なルールが、本来意図されたような哲学の簡潔な表現としてではなく、よいスタイルのレシピとして受け取られているように私は時々感じます。この本が変数名は意味を持つようにつけられるべきだと言うなら、名前が使い方を説明するちょっとしたエッセイのようなものであるほうがいいということになるのでしょうか。MaximumValueUntilOverflowmaxval よりもいい名前ということになるのでしょうか。私はそうは思いません。

これから述べるものは、融通の利かないルールではなく、全体としてプログラミングの明確さという哲学を促進するような短いエッセイ集です。すべてに同意してもらおうとは思いません。これらは意見であり、意見は時とともに変わるものだからです。しかし、これらのことは、文書として書いたことはありませんでしたが、私の頭の中に長い時間をかけて蓄積してきたもので、多くの経験に基づいています。そのため、これがプログラムの詳細を計画する方法についての理解の助けになればと願っています(全体を計画する方法についてのよいエッセイを読んだことはありませんが、この文章は一部それについて書いています)。もし変わっていると思われても、問題ありません。同意できないとしても、問題ありません。しかし、なぜ同意できないかを考えていただくきっかけになれば、そちらのほうが望ましいことです。決して、私がこう言ったからこう書くということをしないでください。プログラムの中で達成したいことを最もよく表現できるとあなたが考えるようにプログラムしてください。また、それを一貫して、容赦なく行ってください。

あなたのコメントをお待ちしています。

表示の問題

プログラムは出版物のようなものです。プログラムはプログラマ自身やほかのプログラマ(それは数日後、数週間後、数年後のあなた自身かもしれません)に読まれるもので、そして最後に機械に読まれるためのものです。機械は、プログラムの見た目の美しさを気にしません。プログラムがコンパイルできれば、機械はそれで満足です。しかし、人間は美しさを気にしますし、気にするべきです。時々、やりすぎになることもあります。プリティプリントを行うプログラムは、プログラムのどうでもいい細かいところを強調するようなきれいな出力を自動的に行います。これ文章助詞すべて太字表示するのと同じぐらい馬鹿らしいことです。プログラムはAlgol-68 Reportのような見た目じゃないといけない(システムによってはそのスタイルでプログラムを編集するよう強制したりもします)と考える人は多いですが、明瞭なプログラムはそんな表示をしてもそれ以上明瞭にはなりませんし、ひどいプログラムは笑ってしまうような結果になるだけです。

もちろん、表示についての一貫した規約は見た目をわかりやすくするためには重要なものです。インデントは、最もよく知られた、最も役に立つ例でしょう。しかし、見た目がプログラムの意図より目立つようでは、表示が主体になってしまっていることになり、本末転倒です。ですから、古き良きタイプライター的出力で通すにしても、表示上の馬鹿げたやり方には気をつけましょう。装飾を避けましょう。例えば、コメントは簡潔に、バナーをつけないようにしましょう。言うべきことはプログラムの中で、簡潔に一貫性を持って言いましょう。それから次に進みましょう。

変数名

そう、変数名です。名前で重要なのは、長さではありません。重要なのは表現の明確さです。めったに使われないようなグローバル変数であれば、長い名前をつけてもいいかもしれません。例えば、maxphysaddr のように。ループ内のすべての行で使われるような配列の添字には、i よりも凝った名前は必要ありません。indexelementnumber といった名前をつけるのは、タイプ量が増える(または、エディタの助けを借りる)ことになりますし、計算の詳細よりも目立ってしまいます。変数名が非常に長くなると、何をしているのかわかりにくくなります。これは、表示の問題の一部でもあります。次の二つについて考えてみましょう。

for(i=0 to 100)
    array[i]=0
for(elementnumber=0 to 100)
    array[elementnumber]=0;

実際の例では、問題はもっとあっという間にひどいことになります。添字はただの記法です。そのように扱いましょう。

ポインタもちゃんとした記法が必要です。np が "node pointer" を指しているということが簡単に導けるような命名規約を一貫して使っていれば、npnodepointer と同じぐらい覚えやすいものになります。これについては次のエッセイで詳しく書きます。

プログラムの可読性に関するほかの側面での場合と同じように、命名においても一貫性は重要です。ある変数に maxphysaddr という名前をつけたら、同種の変数に lowestaddress という名前をつけてはいけません。

最後になりますが、私は最短の長さで最大の情報量のある名前をつけ、残りは文脈から補完できるようにしています。例えば、グローバル変数は普通、使用時にあまり文脈がないので、名前は比較的内容がわかりやすいようなものである必要があります。このため、私はグローバル変数には maxphysaddrMaximumPhysicalAddress ではありません)という名前をつけますが、ローカルで定義して使うポインタには NodePointer ではなく np という名前をつけます。これは感覚によるところが大きいですが、感覚は明瞭さに関わってくるものです。

名前に大文字を入れることは避けています。散文調の文章に慣れた私の目には、大文字は不格好で快適に読めません。ひどい表示の仕方と同じように目障りなのです。

ポインタの使用

C はポインタが何でも指せるという点で変わっています。ポインタは切れ味の鋭い道具です。切れ味の鋭い道具というものは、うまく使うと楽しく生産的になりえますが、間違った使い方をするとひどい傷をつけます(この記事を書く数日前に、私は彫刻刀を親指に刺してしまったところです)。ポインタも例外ではありません。ポインタは危険すぎる、何か汚いものだと思われているため、学術界での評判はよくありません。しかし、私はポインタは強力な記法だと考えています。これは、ポインタは明瞭な表現をする役に立つということです。

考えてみてください。あるオブジェクトに対するポインタがあるとき、それはまさにそのオブジェクトに対する名前であって、ほかのものではありません。些細なことのようですが、次の二つの式を見てください。

np
node[i]

一つ目はノードを指していて、二つ目は同じノードを指すように評価されます(ということにします)。しかし、二つ目の形式は式です。あまり単純なものではありません。解釈するには、node が何か、i が何か、そして inode がその周りのプログラムの(おそらく明記されていない)ルールによって関連づけられているということを知る必要があります。式だけを取り出してみると、inode の有効な添字なのかを知る手がかりはありません。もちろん、望む要素を指す添字なのかもわかりません。もし ijk が全部ノードの配列の添字だとすると、簡単にうっかりミスをしてしまいます。その場合、コンパイラは助けてくれません。特に、サブルーチンに渡すときには間違いを犯しやすくなります。ポインタは単純なひとつのものですが、配列と添字は、それがセットとなるものであることを受け取るサブルーチンのほうで信用しないといけません。

オブジェクトとして評価される式は、本質的にそのオブジェクトのアドレスよりもわかりにくく間違いやすいものになります。ポインタは、正しく使うことでコードを単純にできます。例えば、

parent->link[i].type

lp->type 

です。


もし次の要素の type が必要であれば、

parent->link[++i].type

(++lp)->type

になります。

i は値が進みますが、式の残りはそのままです。ポインタの場合、進めるものはひとつしかありません。

ここでも表示の問題が絡んできます。ポインタを使って構造体の中を読み進めるのは、式を使うよりもずっと読みやすいものになります。インクの使用量も減りますし、コンパイラやコンピュータの労力も減ります。関連した問題として、ポインタの型はその正しい使い方と関係しているので、配列の添字と違ってコンパイル時の便利なエラー検出が利用できます。また、オブジェクトが構造体であれば、フィールドは型を思い出す役に立つので、次のようなものは十分に意味がわかります。

np->left

添字によって配列を使う場合、配列はきちんと選んだ名前を持つことになり、式は長くなってしまいます。

node[i].left

ここでもまた、例が大きくなれば余分な文字はどんどん厄介なものになっていきます。

だいたいの場合、もしあなたのコードに似たような複雑な式がたくさんあって、それらがデータ構造の要素として評価されるなら、ポインタを注意深く使うことですっきりさせることができます。次のコードで、

if(goleft)
     p->left=p->right->left;
else
     p->right=p->left->right;

もし p の代わりに複合式を使っていたらどんな見た目になるか考えてみてください。計算の本質を抜き出すには、時には一時変数(ここでは p)やマクロを使うことが役に立ちます。

プロシージャ名

プロシージャ名は、それが何をするかを表しているべきです。関数名は、それが何を返すかを表しているべきです。関数は式の中で使われるもので、if のようなものの中でよく使われます。そのため、適切に読めるようになっている必要があります。

if(checksize(x))

は不親切です。checksize がエラーのときに true を返すのか、エラーでないときに true を返すのかが推測できないからです。それに対して、

if(validsize(x))

はその点を明確にしているので、将来そのルーチンを使うときに間違いが起こりにくいでしょう。

コメント

これはセンスと判断力が必要となる難しい問題です。私は、いくつかの理由から、コメントをあまり書かないようにしています。ひとつは、もしコードが明確で、よい型名や変数名を使っているなら、コード自身が説明になっているはずだからです。それに、コメントはコンパイラにチェックされないので、正しいという保証がないからです。特に、コードが変更されたあとはそうです。ミスリーディングなコメントは非常に紛らわしいものです。最後に、表示の問題です。コメントはコードをごちゃごちゃにしてしまいます。

しかし、私も時々はコメントを書きます。ほとんどの場合、その次に続くことの説明として使っています。例を挙げると、グローバル変数と型の説明(この場合だけは、大きなプログラムでは必ずコメントを書きます)、あまり見ないプロシージャや非常に重要なプロシージャの紹介、大きな計算セクションの区切りなどです。

有名な悪いコメントというものがあります。

i=i+1; /* i に 1 を足す */

そのもっと悪いやり方もあります。

/**********************************
*                                 *
*          i に 1 を足す           *
*                                 *
**********************************/

i=i+1;

笑うのは早いですよ。笑うのは、実生活で出会ってからでも遅くありません。

コメントでは、かっこいい表示を避けましょう。中心となるデータ構造の宣言のような重要なところは例外としてもいいでしょうが(データに対するコメントは、普通アルゴリズムに対するコメントよりもずっと役に立つものです)、コメントの大きな塊を避けましょう。基本的に、コメントを避けましょう。もしコメントがないと理解できないようなら、理解しやすくなるように書き直したほうがいいでしょう。ここで、次の問題が出てきます。

複雑さ

ほとんどのプログラムは複雑すぎます。つまり、問題を効率的に解くのに必要な以上に複雑だということです。なぜでしょうか。多くの場合、それは設計の悪さが原因ですが、その問題は大きすぎるのでここでは飛ばします。しかし、プログラムは細かいレベルでも複雑すぎることが多いもので、そのことについてはここで書くことができます。

ルール1 プログラムがどこで時間を使うかはわかりません。ボトルネックは驚くような場所で起こるので、ボトルネックの場所を証明できるのでなければ、適当な推測で高速化ハックを入れるのはやめましょう。

ルール2 計測しましょう。計測なしに速度のチューニングをしないでください。計測した場合でも、コードの一箇所がほかの場所に比べて圧倒的に時間がかかっているのでなければ、チューニングはやめましょう。

ルール3 かっこいいアルゴリズムは、n が小さいときには遅いものです。そして、n は普通小さいものです。かっこいいアルゴリズムは大きな定数項を持っているものです。n がよく大きな値になるとわかっているのでなければ、かっこいいことをするのはやめましょう(n が大きくなる場合でも、まずルール2 を使いましょう)。例えば、日常業務の問題では、二分木は常にスプレー木より速いものです。

ルール4 かっこいいアルゴリズムは単純なアルゴリズムよりもバグが起こりやすく、実装が難しいものです。単純なアルゴリズムと単純なデータ構造を使いましょう。

ほとんどの実用的なプログラムでは、次に挙げるリストのデータ構造があれば十分です。

  • 配列
  • 連結リスト
  • ハッシュテーブル
  • 二分木

もちろん、これらを組み合わせて複合データ構造を作る覚悟は必要です。例えば、シンボルテーブルは文字の配列の連結リストを含むハッシュテーブルとして実装されるかもしれません。

ルール5 重要なのはデータです。もし正しいデータ構造を選び、物事をうまくまとめれば、アルゴリズムはたいてい自明なものになります。プログラムの中心は、アルゴリズムではなく、データ構造です。(詳しくは「人月の神話」を参照してください)

ルール6 ルール6はありません。

データでプログラムする

アルゴリズムや、アルゴリズムの細かいところは、たくさんの if 文のようなもので書くよりも、データとして書いたほうが、効率よく強力に記号化することができることがよくあります。その理由は、手元の仕事の複雑さが独立した細かい部分の組み合わせによるものであれば、記号化できるからです。典型的な例としては、パージングテーブルというものがあります。プログラミング言語の文法を、定型のかなり単純なコードによって解釈できる形に記号化したものです。この手のやり方としては有限状態機械が特に柔軟に使えますが、何らかの抽象的な入力を「パージング」して何らかの独立した「アクション」列にするようなプログラムであれば、どんなものであってもデータ駆動アルゴリズムにすることでいい結果が得られるでしょう。

このような設計のおそらく最も興味深い側面は、テーブルがほかのプログラムによって生成されることもあるということです。典型的な例でいうと、パーザジェネレータがあります。もう少し身近な例としては、OSがI/Oリクエストを適切なデバイスドライバに割り当てるテーブルによって動いている場合、マシンに接続されたデバイスについての記述を読み込んで対応するテーブルを表示するようなプログラムで「設定」できるでしょう。

データ駆動プログラムが(少なくとも初心者の間で)一般的でない理由のひとつは、Pascalの独裁です。Pascalは、その作者同様、コードとデータを分割することを固く信じています。そのため、(少なくとも元の形では)初期化されたデータを作ることができません。これは、プログラム内蔵方式の原則を定義したチューリングフォン・ノイマンの理論に真っ向から喧嘩を売っています。コードとデータは同じものです。少なくとも、同じにすることができます。そうでなければ、コンパイラがどうして動くのか説明できないでしょう。(関数型言語はI/Oに関して同じような問題を抱えています)

関数ポインタ

Pascalの独裁の結果には、初心者が関数ポインタを使わないということもあります(Pascal では関数を値に持つ変数を使えません)。複雑さを記号化するために関数ポインタを使うことには、いくつかの面白い性質があります。

複雑さの一部は、ポインタの指すルーチンに渡されます。ルーチンは、同じように呼び出されるルーチンセットのひとつとなるので、何かしらの標準プロトコルに従う必要があります。しかし、それより重要なのは、ルーチンが自分の責任範囲のことしかしないということです。複雑さは分散されることになります。

このプロトコルという考え方は、同じような使われ方をする関数は同じようなふるまいをしなければならないというものです。このことが、ドキュメントの記述やテスト、プログラムの発展をやりやすくしています。さらには、プログラムをネットワーク越しに動かすこともやりやすくなります。プロトコルは、リモートプロシージャコールとしても記号化できるのです。

私の主張は、オブジェクト指向プログラミングの核心となるものは、関数ポインタを明確に使うことだというものです。データについて実行したい操作セットがあり、それらの操作に対して適用したいデータ型のセットがあるなら、プログラムをまとめる一番簡単な方法は、それぞれの型に対して関数ポインタのグループを使うというものです。これは、一言で言うと、クラスとメソッドを定義するということです。もちろん、オブジェクト指向言語にはそれ以上のものがあります。きれいな構文、派生型など。しかし、概念的には、ほとんど変わるところはありません。

データ駆動プログラムと関数ポインタを組み合わせると、びっくりするほど表現力のある書き方ができるようになり、私の経験では、意外な喜びをもたらしてくれることもよくありました。特別なオブジェクト指向言語なしでも、余計な手間なしでオブジェクト指向のいいところの90%を手に入れることができ、結果についても自分でコントロールしやすくなります。これほどお勧めできる実装スタイルはありません。この方法で構築してきたプログラムは、かなりの開発を重ねてもうまく生き残っています。もっとゆるいやり方の場合よりも、ずっといい結果です。きっと、この手法に求められる規律は、長い目で見ると割に合うということでしょう。

インクルードファイル

単純なルールです。インクルードファイルはインクルードファイルを決してインクルードしてはいけません。その代わりに、どのファイルを先にインクルードするべきかが(コメントで、または暗黙的に)言明されていれば、どのファイルをインクルードするべきかという問題はユーザ(プログラマ)に押しつけられますが、ある意味では扱いやすく、組み立て方によって多重インクルードを避けることができるようになります。多重インクルードはシステムプログラミングの癌です。ひとつの C のソースファイルをコンパイルするのに、5 回以上もインクルードされるファイルがあることは珍しいことではありません。この面から言うと、Unix/usr/include/sys はひどいものです。

#ifdef を使ってファイルが 2 回読まれないようにする小手先のテクニックがありますが、実際には正しく運用されないものです。#ifdef はファイル自身の中にあり、インクルードする側にあるのではありません。結果として、何千行もの不要なコードが字句解析器に渡されることになってしまいます。これは、(良いコンパイラの場合)最も負荷の高いフェーズになってしまいます。

単純なルールに従いましょう。