SWI-Prolog と日本語変数名と Singleton variables 警告
2015年03月21日(土)00時47分
無名変数
Prolog では「英大文字かアンダーラインで始まる文字列」が変数として扱われますが、その他に、アンダーライン一文字のみの、「無名変数」と呼ばれる特殊な変数があります。
この無名変数が使われるのは、「節のなかに一つしかなく、その値がなんであろうが構わない」という場合です。
例えば、再帰処理の停止条件として「ある引数が 0 ならば真」というような節を定義することがありますが、その場合、他の引数は何であろうと関係がありませんので、それらは無名変数にできるわけです。
「Singleton variables:~」警告
で、他の処理系は知らないのですが、少なくとも自分の使っている SWI-Prolog では、この「無名変数にできる引数」は「無名変数にすべし」という方針となっているようで、つまり、無名変数にしないと 警告(Warning)が出ます。
例として、非常に単純化した、以下のような節を考えます。
test(_a).
この場合、「_a」の部分が何であっても成立するため、「_a」にはあえて名前を付ける必要がありません。
これを SWI-Prolog で実行しますと、次のような警告がなされます。
Singleton variables: [_a]
タイプミス防止
なぜこのような方針となっているのか?ですが、これは「タイプミスによる予期せぬ孤立変数」の検出に役立つから、であるようです。
Prologでは、使用する変数名を事前に宣言等で明示する必要がありません。
そのため、うっかりタイプミスをして、違う変数名になってしまっていても、「そういう名前の新しい変数」として、そのまま実行されてしまいます。
これは、場合によっては物凄く見つけにくい厄介なバグになるのですが、しかし、タイプミスした変数名が一つだけであれば、それは「一度しか使われていない孤立した変数」となるため、上記「無名変数の警告」によって気づくことができるというわけです。
二重アンダーラインによる回避
しかしながら、一度しか使用されない変数であっても、「その引数の役割をコメント的に書いておく」等の理由により、あえて名前を付けたいこともあります。
こういった用途のために、SWI-Prolog では、アンダーラインを二重に付けることで、「無名変数の警告」を抑制する仕組みが用意されています。
前述の例であれば、以下のように「_a」の前にもう一つ「_」を付け、「__a」とすることで警告が出なくなります。
test(__a).
また、変数名が英大文字から始まる場合は、(本来不要である)アンダーラインをあえて付けることで、「意図的に名前を付けた無名変数」にできます。
つまり、以下のようにすることで、「無名変数の警告」が出なくなります。
test(_A).
「Singleton-marked variable appears more than once:~」警告
ちなみに、以下のような節を実行すると、「Singleton-marked variable appears more than once: __a」という警告が表示されます。
test(__a,__a).
これは、「一度しか使われないはずの無名変数が二度(以上)使われている」という警告です。
当然ですが、これは「_」を一つ削って、以下のような「通常の変数」にしてしまえば、警告を防ぐことができます。
test(_a,_a).
どうしてこんな当たり前のことをわざわざ書いたのか?と言いますと、次で述べる「日本語変数名における奇妙な振る舞い」に関係するためです。
日本語変数名での問題
ということで、ここからやっと、本題である「日本語変数名」についての問題になります。
なお、ここで言う「日本語変数名」というのは、「漢字かな交じり文」というべきか、UNICODE 文字というべきか、ともかく非 ASCII 文字で構成された文字列のことです。
SWI-Prolog では、この「日本語変数名」は、普通に使用することが可能です。
ただしこれらは、「先頭が英大文字」という Prolog の変数名規則を満たすことができないため、当然ながらアンダーラインで始める必要があります。
test(_あ).
もちろん、上記は「Singleton variables: [_あ]」の警告が出るため、以下のような二重アンダーラインで回避するのも同様です。
test(__あ).
そして、以下の記述では「Singleton-marked variable appears more than once: __あ」と警告されるのも、すでに述べたとおりです。
test(__あ,__あ).
問題はこの次で、上記の警告を回避するため、以下のようにしても、「Singleton-marked variable appears more than once: _あ」の警告が出されるのです。
test(_あ,_あ).
仕様?
これについては、SWI-Prolog サイトの「Singleton variable checking」項に以下のような記述があり、どうも現在のところ、これが仕様とされているように思われます。
As Unicode requires variables to start with an underscore in many languages, this schema needs to be extended.
ともあれ、一つの節に、同じ名前の「日本語変数」が複数存在すると、「Singleton-marked variable appears more than once:~」警告が出るわけです。
そして、「一つの節で同じ名前の変数が複数回使用される」というのは、Prolog では当たり前のこと(一度しか使われないのであれば無名変数でよい)であり、つまり、SWI-Prolog において、「日本語変数名」を多用すると、「警告まみれ」となってしまうのです。
回避策その一「英語を使う」
で、この問題への回避策としては、まずは身も蓋もないのですが「日本語変数名を使わない」という方法が考えられます。
自分自身は「日本語変数名」については、容認派…というより、むしろ可能であれば積極的に使いたいとすら思っているぐらいです。
しかしながら、Prolog に限らず、世にあるメジャーなプログラミング言語は、そのほとんどが外国製であり、もともと「日本語を使うことなど想定されていない」ということも多いのが実情です。
そのため、実際のところ「できる限りアルファベットのみで記述する」というのは、「余計な苦労を避ける」という点において、有意な選択肢ではあるかと思います。
回避策その二「:- style_check(-singleton).」
とはいえ、それではあんまりですので、その他の回避策としては、コンパイラに対して、これらの警告を出さないように指示するという方法が考えられます。
:- style_check(-singleton).
上記の行を、ソースコードの冒頭にでも書いておくことで、「singleton」系の警告を非表示としてしまうわけです。
もちろん、これによって本来の目的である「タイプミスによる意図せぬ変数の発見」という恩恵も受けることができなくなります。
が、もし日本語変数名を多用するのであれば、いずれにしても「警告の洪水」にまぎれ、本当に必要な警告も確認しなくなったりしますので、あまり問題にならないような気はします。
「ハンガリアン記法」という考察
もう一つ、回避策というべきか、折衷案的なものですが、「ハンガリアン記法を導入する」という手もアリなのではないか、ということで、少し考察してみました。
いわゆる「ハンガリアン記法」には、提唱者が本来意図していた「アプリケーション・ハンガリアン」と、その誤解を基に広まった「システム・ハンガリアン」の二種がありますが、ここでは後者、つまり「変数名にデータ型を表す接頭語をつける記法」のことです。
まず、ここまでに述べてきた「日本語変数名の問題」というのは、変数名の先頭のみでも英大文字にしてしまえば、「先頭が英大文字」という、ごく普通の Prolog 変数名となり、無視できるのです。
そこでこれを応用し、例えば、その変数に期待される値がアトムなら「A_」、数値なら「N_」、リストなら「L_」、アトムか数値なら「C_」、何でもよければ「V_」を接頭詞として付ける、というようなコーディング規則を設けるわけです。
こうすることで「標準的な Prolog 変数名」となりますから、無名変数にあえて名前を付ける場合においても、SWI-Prolog の仕様に即して「先頭にアンダーラインを付ける」ことで、警告を回避できます。
これによって、日本語変数名を使用しつつ、タイプミス発見につながる警告も受けることができるようになります。
ということで、「SWI-Prolog」かつ「日本語変数名を多用する」というスタイルを前提とするのであれば、「ハンガリアン記法」という選択も悪くないのではないか、と思いました。
…実際のところ、自身の Prolog 経験は、いまだ「サンプルコードの写経」的な、非常に浅いレベルにとどまっていますので、実用の段においては、ただちに破綻するような論であるのかもしれないのですが。
- 関連記事
-
- Mery(テキストエディタ)で Prolog ソースコードの色分け表示
- Prolog の組み込み演算子一覧が欲しい
- Prolog の組み込み述語一覧が欲しい
- SWI-Prolog と日本語変数名と Singleton variables 警告
- Prolog、わかりはじめる?
- Prolog がわからない
- SWI-Prolog Portable を試す