4D ローカル変数名にコロンが含まれていた

4Dでは、メソッド間で、たとえば呼び出す側が2つ引数を渡す時、呼び出される側のメソッドは第1引数を$1で、第2引数を$2で参照する。しかし引数名のまま$1や$2で参照すると、渡される値が何かがわかりにくいし、後で引数の順番が変わった時に不具合の元になるため、次のように記述して、引数をローカル変数に代入してから使うことにしている。こうしておけばREAD ONLY以降のコードを再利用しやすくなる、というオマケも期待できる。

C_LONGINT($1;$tr_id)
$tr_id::=$1
C_OBJECT($2;$objTR)
$objTR:=$2
C_TEXT($0;$numOfRecs)
READ ONLY([TRADEMARK])
QUERY([TRADEMARK];[TRADEMARK]TR_ID=$tr_id)
$numOfRecs:=Records in selection([TRADEMARK])
If ($numOfRecs=1)
  //オブジェクトで値を返す
$objTR.bikou:=[TRADEMARK]TR_BIKOU
End if 
$0:=$numOfRecs

上記のコードをよくみて欲しい。一つ目のローカル変数名にコロンが含まれていたのだ。これが不具合の原因だったのにしばらく気付かなかった。4Dは変数名にコロンを含んでていても構文エラーにならない。

たとえば「$tr_id:」をダブルクリックすると、「$tr_id」部分(コロンなし)が選択される。コピーして検索ダイアログを表示してペーストして検索実行すると、以下のコードの「$tr_id」は検索にヒットするため検索条件は正しく記述されているように見えて誤りに気付きにくい。ダブルクリック時に「$tr_id:」(コロンつき)を選択できていれば、検索実行で以下のコードにコロンつきの変数名がヒットしないことがわかったはず。そこで、変数名のタイプミスに気づくはずだ。

実行時のエラーにもならない。「$tr_id:」という変数に$1の内容を代入、QUERYでは未代入の「$tr_id」(値はゼロ)でクエリーしているだけだからだ。デバッガーで見ると呼び出した側は正しい値を与えているのに、なぜか期待した値がヒットしない、という結果になる。

「変数名にコロンを使える」という4Dの仕様に問題があるような気がする。「=」とか「-」を変数名に含めると構文エラーになるのに。

コロンを変数名に含めて良いのであれば、コロンが含まれた変数名をダブルクリックして選択した場合にコロンも選択範囲に含めてほしい。誤りに気づきにくい仕様になっていると思う。今回たまたま画面解像度が高くて文字が小さくなっていて、さらに焦ってコーディングしていたという事情はある。それにしてもこれまでこの事故が起こらなかったことが不思議だ。目視ですぐに気づいていたのか、こんなところでタイプミスはしなかったのか、老眼が進んでいなかっただけなのか?

試してみたらプロセス変数名も同様にセミコロンを含めることができた。見れば分かるだろというコーディングミスではあるけど要注意、というお話。

今回のハマりレベルは3、一人では抜け出せなかった。ハマりレベルとは、1:自力解決、2:ドキュメントで解決、3:他者によるサポートにより解決、4:翌日以降に解決、5:未解決。