2009-12-31

C++0xの本について考える

完全に言語として解説すべきかどうかが問題だ。

たとえば、lvalueとrvalueの違い、reference、move semanticsは、お互いに深く関係している。では、これらをひとまとめにして、同じ場所で解説していいものか。最初、厳密に分けるべきだと考えて、その後、思い直したが、やはり、厳密に分けるべきではなかろうか。

まず、move semanticsは、言語の機能ではない。むしろ、プログラミングのテクニックに属する。しかし、この前、rvalue referenceを完全に解説すると称して、そのような記事を書いたところ、少なからぬ人が、勘違いをしていた。どのような勘違いかというと、「std::move()に変数を渡したら、その変数は、それ以降は使えなくなるようだ」、「std::forward()は、template以外のコードでも使うのだろうか」などといった誤解である。

これは畢竟、move semanticsは、言語機能であると勘違いしているからなのだ。std::move()やstd::forward()とは、なにかコンパイラが生成する魔法の関数のように考えているのだろう。しかし、実際はcastでしかない。単なるreferenceへのcastなのだ。rvalue referenceで出来ることは、lvalue referenceでもできる。ただ、関数に渡したオブジェクトが、その関数内で勝手に破壊されたとあってはたまらないので、あまりそのようなコードが書かれないだけなのだ。rvalue referenceは、そのコードを安全に書くための方法である。

また、std::forward()に関して。これは、templateのargument deductionがあるために、必要なのだが、誤解している人は、argument deductionについてよく知らないから、誤解しているのだ。Bjarne Stroustrupはインタビューで、普通のプログラマが、std::move()やstd::forward()の実装について理解している必要はないと言った。しかし、std::forward()の実装を知らないが、templateのargument deductionは完璧に理解しているという、普通のプログラマがいるのだろうか。

とすれば、この三つの項目は、完全に章節を分けて、分離したほうが良い。純然たる概念と、言語機能と、テクニックは、別物である。lvalueとrvalueの違いについては、言語の基本的な概念である。referenceは、言語の文法である。move semanticsは、プログラミングのテクニックやライブラリに属する。

このように厳密に分けることは、「細かいことなんてどーでもいーから、さっさとmove semanticsとやらを使いたいんだよ。コードが速くなるって聞いてるしな。最適化のためなら何だってやるぜ」という類のプログラマの不評を買うだろう。そうでなくとも、読者は「なお、この機能に関係のある某機能については何章を参照されたし」という記述を見て、飛び飛びに読まなければならない。それでも、誤解を招くよりはいい。

すでに世に出回っている、パーフェクトC#という本は、goto statementと、goto statementに使うlabelを、別々に記述していた。これは私の、厳密に分けるという理想を後押しする。厳密に分けるのが、最も正しい記述法であると信ずる。結局、これは入門書ではないのだから。

用語の問題だ。私は今、下手に訳さずに、アルファベット表記することを、本気で思案している。

たとえば、referenceの一般的な訳語は、参照だ。しかし、これで意味が分かるだろうか。みな、「サンショー」という音だけで覚えているのではないか。「pointerは変数を参照する」というような記述は分かる。この場合の参照は、日本語として機能する。ところが、「この機能は、参照という名前である」という記述は、わけが分からない。だったら、「この機能は、referenceという名前である」でもいいのではあるまいか。

就中、今回のC++0xには、constructorのdelegationやら、exception propagationやら、実に翻訳に困る概念がたくさん入っている。デザインパターンの世界では、delegationを、委譲と訳しているようだが、どう考えても、addressを番地と訳すのと同じぐらい泥臭い訳である。

ただし、アルファベット表記にも問題がある、ポインタとか、キャストなどといった、もう十分浸透しているだろうというような単語にまで、これを適用するのは、だいぶ難しい。この文章では、実際にそのような記述をしてみた。ただし、関数とかオブジェクトのような言葉は、さすがにやめておいた。

「instantiationする」ならまだともかく、「castする」という言葉は、どうも違和感がある。第一、これを厳密に、全文に適用するならば、「pointerを参照する」という文章にしたって、「pointerをdereferenceする」となってしまう。ここまでするぐらいなら、英語で書いた方がマシではあるまいか。

ひとつ思うのは、この文章は、動詞だからまずいのではないかということだ。つまり、サ変活用を、「英単語+する」などと使うからまずいのではあるまいか。名詞は英単語にしておいて、動詞だけ訳すというのはどうか。現に、「reinterpret_castでpointerを数値にキャストする」という文章なら、全く問題なく読めるはずだ。

しかし、delegateや、instantiateのような動詞は、依然として訳しづらい。「デリゲートする」、「インスタンシエイトする」という文章で、通じるだろうか。少なくともdelegateについては、「委譲する」などという奇妙な日本語より、マシだと思うのだが。

あのイケメンのアキラさんの書いた、C++ テンプレートテクニックでは、「インスタンス化する」という表現を用いている。たしかに、化という接尾語は、ニュアンス的にもわかりやすい。

しかし、これにも例外を設けなければならない。関数、変数などといった有名な言葉は、さすがにこのルールを適用するのは難しい。

私がこのようなことを考えるのは、単に用語の翻訳の難しさから逃げるためばかりではない。思うに、技術者というのは、英語が使えなければならない。海外のフォーラムやIRCでは、boostをいとも当然のごとく使っているのにも関わらず、国内では、STLさえまともに使えないC++プログラマがいる。これは結局、日本語のドキュメントに乏しいからだ。結局英語を使わねばならぬのだとしたら、英単語に慣れていた方がいいのではなかろうか。プログラミング関係の英語は、小説のように難しい表現など出てこない。単語さえ知っていれば、分かるのである。

1 comment:

dark-yoshi said...

I wish you could write in English.