CodeZine(コードジン)

特集ページ一覧

自然な思考で当たり前のプログラミングを~Bjarne Stroustrup氏との対話~

第7回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2008/12/24 14:00

目次

Stroustrup氏の回答2: 私は第1のコードを好みます

I prefer the container form

 

  auto q = find(vi, 7);

 

while others consider the iterator form clearer

 

  auto q = find(vi.begin(), vi.end(), 7);

 

First note that both give the same answer and given decent inlining (as provided by current compilers) there is no performance difference. This is purely a question of programming style. The way I would phrase the fundamental question is "Which use of find() expresses our intent most clearly?" Let's add comments:

 

  auto q = find(vi, 7);  // find 7 in vi

              // i.e., find the first 7 in vi

              // i.e., find the first 7 in [vi.begin():vi.end())

 

  auto q = find(vi.begin(), vi.end(), 7); // find the first 7 in [vi.begin():vi.end())

 

That is, the precise statement of the meaning of first call is almost exactly the second call. But how precise do we want to be? I think that "find 7 in vi" is the way most people think of that operation. Thinking about a container as a sequence, being explicit about "first", and "first" as "the first element in that sequence" secondary in their minds. For that reason, I'd prefer find(vi, 7). Secondarily, I'll observe that that's less to type and opens fewer opportunities for mistakes. For example:

 

  auto q1 = find(vi.begin(), vi.begin(), 7); // oops!

  auto q2 = find(vi.begin(), vj.end(), 7);  // oops!

 

However, every notation can of course be misused and we absolutely need the sequence form because it is the more fundamental and general. For example, given only the container form, it would be complicated to find something in half a container; with the sequence form it's easy:

 

  auto middle = vi.begin()+vi.size()/2;

  auto q1 = find(vi.begin(), middle, 7);

  auto q2 = find(middle, vi.end(), 7);

 私の好みは、次の順序です。

auto q = find(vi, 7);
auto q = find(vi.begin(), vi.end(), 7);

 これら2つのアルゴリズムは同一の結果を返してくれます。この点をまず確認しておきます。また、パフォーマンス面での違いもありません(現在のほとんどのコンパイラーはインライン処理してくれますから)。いずれのアルゴリズムを採用するかは、純粋なプログラミングスタイルの問題です。このため、あなたの質問は「どちらのfind()が私たちの意図をよりはっきり表現してくれますか?」と言い直した方がよいでしょう。ここでコメントを追加させてください。

auto q = find(vi, 7);   // vi内の7を見つけ出す
                        // i.e., vi内の最初の7を見つけ出す
                        // i.e., [vi.begin():vi.end()]範囲にある最初の7を見つけ出す 
auto q = find(vi.begin(), vi.end(), 7); //  [vi.begin():vi.end()]範囲にある最初の7を見つけ出す

 ご覧のように、第1コードの意味と第2コードの意味はほとんど同じです。しかし、精度の高さという点ではどうでしょうか。ほとんどの人は、「vi内の7を見つけ出す」という思考プロセスを経るのではないかと思います。コンテナーをシーケンスと考えてしまえば、「最初の」は自明です。「最初の」を「シーケンス内の最初の要素」と考えるのは二次的なプロセスではないでしょうか。これが第1コードを好む私の説明です。次に、タイプミスをはじめとする各種のケアレスミスを防止するという利点もあります。例えば、

auto q1 = find(vi.begin(), vi.begin(), 7);     // 構文エラーあり
auto q2 = find(vi.begin(), vj.end(), 7);       // スペルミスあり

 とはいっても、すべての表記法は誤用される可能性を残しています。第2コードは基本的なものであり、より高い汎用性を持っているため、厳密なシーケンスを必要とします。例えば、コンテナーレベルのアルゴリズムだけを使用すると、コンテナーの中間位置にある何かを見つけ出す処理は複雑になってしまいます。第2コードのようなイテレータでシーケンス範囲を明示した方がロジックを簡単に組めることになります。

auto middle = vi.begin()+vi.size()/2;
auto q1 = find(vi.begin(), middle, 7);
auto q2 = find(middle, vi.end(), 7);

対話のポイント:

 筆者は極めて単純な2つのコード「auto q = find(vi, 7);」と「auto q = find(vi.begin(), vi.end(), 7);」を示しながら、C++設計者としてどちらのコード記述を推奨するかを尋ねています。Stroustrup氏は、「auto q = find(vi, 7);」の方を挙げ、その理由を説明してくれています。筆者はその説明に目を通した時、やっぱり!、と思いました。同氏は「人間的な思考」を持ち出しています。「最初の」を「シーケンス内の最初の要素」などとあまり(厳密に)考えないというわけです。

 Stroustrup氏は以前、筆者からの別のインタービュー(参照ページ:豊田孝のIT談話館)に応じ、システムの規模が大きくなればそれを記述するプログラミング言語は複雑になるという認識を示す一方で、「言語構造がどれほど複雑になっても、その構造は自然界と人間社会に既に存在する」ことを強調しています。言われてみれば、名前空間、型、アドレス、インスタンス、例外、関数、キャストなどは、名称こそ異なりますが、確かに自然界と人間社会に既に存在している印象を受けます。筆者は、Stroustrup氏、Stepanov氏、両氏の出会いを演出したAndrew Koenig氏などの論文や発言内容に目を通すたびに、「彼らの斬新な発想」に驚かされます。

 Stroustrup氏は、プログラミング言語「C++」を設計しただけではなく、20年以上の長期に渡り、その発展のために努力してきました。これは事実だと思いますが、より正確には「Stroustrup氏は20年以上に渡り、自然界と人間社会をみつめ、その成果をC++に反映しようとしてきた」、と表現しても間違いではないしょう。なら、人生を賭ける価値と魅力がそこにある、と考えます。そして、誠に羨ましい!、と嘆かずにいられません。皆さんはいかがでしょうか?

 本連載は以上で終了いたします。長い間のご閲覧、ありがとうございました。



  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:Bjarne Stroustrup氏との対話

著者プロフィール

  • 豊田 孝(トヨタ タカシ)

    「Windows PowerShell実践スクリプティング―オブジェクト指向と集合指向の統合シェル」(秀和システム発行)と「IT技術者として生き抜くための十ヶ条」(翔泳社発行)の近著2冊にて本音の数%を吐露。最近の活動傾向は、こちらを参照してください。  

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5