flint>flint blog>2013年>10月> 4日>自然言語の呪縛

自然言語の呪縛

コンピュータ関連の仕事をしている人ならば誰でも、多少の差はあれ、普段の会話に使っている言葉 (いわゆる 自然言語) とは異なるコンピュータ言語と呼ばれるものを使っています。 次のようなものがそれに該当するでしょう:

これらの言語は、対人の会話や叙述をするためのものではないため、それが表す内容や想定される受け手 (コンピュータプログラム) に応じてより適切な、自然言語のそれとは異なる記法・文法を備えています。 とはいえ、コンピュータ言語にはマン=マシンインターフェイスとしての側面もあり、人間にとってもある程度は理解しやすいものであることが求められるため、そこには自然言語 (大抵は英語) をベースにした語彙や構文が用いられており、完全にコンピュータのために設計された言語とはなっていません。

その最も顕著な例であるSQLでは、テーブル customer から、名が "Henry" である列を探し出すためのクエリは以下のように記述されます。

SELECT * FROM "customer" WHERE "firstname" = 'Henry' ORDER BY "lastname", "id";

このステートメントは英語の命令文と多くの共通点を持っているため、英語が読める人であれば、その動作の詳細は分からなくても、そのおおまかな意味を掴むことは難しくないはず。 その一方で、そこには「自然言語に似せたこと」に由来する冗長さが包含されてしまうこともしばしば。 例えば、列を取り出す順序を指定する "ORDER BY" 句に着目すると、SQLではキーワード "ORDER" は (私の知る限りでは) 必ずその後にキーワード "BY" を伴うため、記述される情報の量に全く寄与しない制約が生まれてしまっています。 (同様の問題は "PRIMARY KEY" や "NOT NULL" でも見られますね。)

このような言語仕様に組み込まれてしまっている冗長さ・不合理さは、そう簡単に解消できるものではありませんが、個人 (あるいは企業) が用いる変数名や関数名の規則であれば、ちょっとした発想の切り替えでより簡潔で合理的なものにできるかもしれません。

主幹となる語を前に

プログラム内で用いる変数は、その名前を名詞の形にするのが一般的です。 以下は、双方向の連結リストを構成する各ノードにおいて、自身の次のノードと前のノードを表すポインタの宣言です。

ListNode<T>* previousNode;
ListNode<T>* nextNode;

どうも見づらいですね。 同じコンテキストで用いられる変数がこれだけであればともかく、他にもたくさんの変数がある状況では、この二つが対になっていることを読み取るにはちょっとした注意力が必要です。

では、なぜこれが対であることが分かりにくいのかというと、共通する語 (この場合は "node") の位置が揃っていないため。 日本語あるいは英語に慣れている私たちは「形容詞は修飾の対象となる名詞の前に置かれる」というルール (文法) にあまり疑問を持ちませんが、データ構造のロジックから考えると、より重要な概念を上位 (前方) に、付随的な情報は下位 (後方) に置くのが自然です。 これを踏まえて、形容詞 (previous/next) と名詞 (node) の位置を反転させてみましょう。

ListNode<T>* nodePrevious;
ListNode<T>* nodeNext;

これでだいぶ可読性が向上したような気がするのですが、いかがでしょうか。 ただし、これだけでは「"node" の位置が揃っていれば、それが前方でも後方でも同じことだろう」という反論が出ることが考えられるので、形容詞の字数を合わせるために、"previous" を短縮形の "prev" に変えてみます。

ListNode<T>* prevNode;
ListNode<T>* nextNode;

やはり、先の形容詞を後ろに置くルールの方が見やすいように思います。 そもそも、組になる形容詞に字数が揃う短縮形があるというのは稀なケース。 他にプログラミングでよく用いられる語のグループとして "begin" と "end"、"main" と "sub"、"left" と "right" (と "center"/"middle") などがありますが、いずれも一般に通じる短縮形はありません。 もちろん、短縮形が使えるならば、「名詞を前に」のルールと併用すればより見た目を良くできるでしょう。

ListNode<T>* nodePrev;
ListNode<T>* nodeNext;

更に言うならば、英語の「形容詞が名詞の前にくる」という文法は、それが属するインド・ヨーロッパ語族では必ずしも一般的なものではなく、イタリア語やスペイン語、フランス語では形容詞は (殆どの場合) 名詞の後に置かれます。

形容詞的用法を原形で

データベースなどでよく見られる設計パターンとして、各列 (レコード) に「登録日時」と「最終更新日時」を保持させるテーブル定義があります。 その場合、それらの情報を格納する列 (フィールド) は次のように定義される場合が多いようです。

registered_time  TIMESTAMP  NOT NULL,
updated_time     TIMESTAMP  NOT NULL,

まず、これらの列名に前節の「形容詞を後ろに」というルールを適用してみましょう。

time_registered  TIMESTAMP  NOT NULL,
time_updated     TIMESTAMP  NOT NULL,

これはこれで良い気もしますが、個人的には "time_registered" が15文字と長いのが気になります。 これをもう少し縮める方法はないでしょうか。 そのための手法として、私は「○○される (/された) 日時」のように、動詞の過去分詞形や進行形で修飾されるフィールドには、代わりに原形を使用することにしています。 (例: 履歴を取ってみよう)

time_register  TIMESTAMP  NOT NULL,
time_update    TIMESTAMP  NOT NULL,

この例だとわずか2文字の省略で、あまり可読性への寄与がないばかりか、英語の文法に違反しているため、却って有害であるように思えるかもしれません。 しかし、これがイベントの「開始日」と「終了日」を表すフィールドの名前だったらどうでしょう。 「開始」を表す動詞は "begin" ですが、この「開始日」には (登録の時点から見て) 未来の日付が格納されるため、過去分詞形 "begun" を用いることは適切ではありません。 そのため、進行形である "beginning" を用いたくなるところですが、これは長い上に、「終了」を表す "end" はそのままで「終りの」という意味の形容詞として作用するため、統一感がない上に字数の差もかなり大きくなってしまいます。

date_beginning DATE  NOT NULL,
date_end       DATE  NOT NULL,

この "begin" と "end" のように、格変化に対称性がない動詞群として、"open" と "close" があります。 "open" には「開かれた (ている)」という形容詞的用法がありますが、"close" にはそれがありません。 「閉じた」という意味を表すには、"closed" にする必要があります。 その他にも、"begin" と "end" の代わりに "start" と "finish" を使ったらどうか、など考えられる対応は色々とありますが、いずれもプログラム作成者の語彙あるいは語学力への依存が大きくなってしまい、工学的な観点からはあまり好ましくないものに。

その点、ここで挙げた原形を用いる方法であれば、動詞の格変化の影響を考える必要がなく、意味上の混乱が起こる恐れもまずありません。

date_begin  DATE  NOT NULL,
date_end    DATE  NOT NULL,

余談ですが、「更新日時」(DATETIME/TIMESTAMP型)を表すフィールドは "updated_at" 、「更新日」(DATE型) を表すフィールドは "updated_on" とする命名法もよく採用されているようです。 (Ruby on Rails の影響でしょうか?) しかしこれは、「"at" の後には時刻、"on" の後には日付が来る」という英語の前置詞の用法に由来するもので、ネイティブスピーカとまでは言わずとも、ある程度以上英語に通じた人でなければ判断が難しい部分。 (そもそも名詞句ですらなくなっていますし。) 例えば、日本語プログラミングにおいて、「家を数えるときは『棟』、箪笥を数えるときは『竿』、包丁を数えるときは『振』、...」という助数詞の使い分けのようなプログラミングに本質的でない知識を前提とされたら、非日本語話者にとって大きな混乱のもとになるでしょう。 それと同じ問題が、この命名法には潜んでいます。

さらに言えば、個人的にはひまわりなでしこに代表される日本語プログラミング言語は、助詞の用法などプログラムにとって非本質的な言語知識を持ち込む方向に作用するため、できればあまり普及しないで欲しいところ。 日本語に限らず、コンピュータ言語が「自然言語に近い」ことを売りにするのは目的と手段が逆転しているだろう、というのが私の考えです。

私の常識はあなたの非常識

コンピュータ技術者にとっても、語学というのは身についているのに越したことのない素養。 特に語彙は、適切な命名を行う上で非常に重要です。 しかしその反面、自分が慣れ親しんだ言語について、人はそのルールを疑わなくなりがち。 日本語しか話せない人は冠詞や複数形などの概念は持たないでしょうし、英語を学んだとしても、名詞の性という概念には思いもよらないでしょう。 そして、そうした「常識」に囚われてしまうと、こうしたコンピュータ言語を設計あるいは使用する段階で、知らず知らずのうちに、特定の言語に依存した、目的に対して非本質的な習慣を持ち込んでしまうことになります。

そうした不合理を避け、より本質に近く無駄のない設計を行うには、言語に依存しない抽象的な思考が必要なのかもしれません。 英語では、住所は小区分から大区分へという順番で記述していきますし、人名は名が姓よりも先に書かれます。 ドメイン名の記法も、そうした習慣に倣ったものでしょう。 にも関わらず、同じ英語の文化圏で生まれたファイルパスの記法は大分類から小分類へという順になっています。 これは、ディレクトリの入れ子として表現されるデータ構造が、本質的にその順で記述される性質を備えているからに他なりません。 もしこの記法が逆順であったらどうなるかと想像すると、その扱いにくさに頭が痛くなってきます。 (ドメイン名は一般的にそれほど長くならないので、問題が顕在化しにくい。)

もちろん、それまでの経緯や文化的な背景というものも決して軽んじてよいものではありませんが、少なくとも「それが個別の習慣に起因するルールである」ことが意識されているか否かによって、設計の質に大きな差が出てくることは間違いありません。 文化や習慣に優劣や唯一の正解はありませんが、現在の目的に対してより適した方法を選ぶ努力は欠かさないようにしたいものです。

関連記事

成田 (また記事タイトルに「呪」という字を入れてしまった...。)
このエントリーをはてなブックマークに追加

コメント

投稿者
URI
メールアドレス
表題
本文