コンパイラは、4Dコマンドの通常の構文ルールに従っていることを期待します。コンパイルのためにデータベースを特に変更する必要はありません。
とはいえ、この節ではコマンドについての注意点や詳細について項目別に説明します。
変数のデータ型を決定付けるようなコマンドは、データ型矛盾の原因になることがあります。 コマンドの中には複数のシンタックスを持つものがあり、どのシンタックスが最適なのか知っておくと役に立ちます。
文字列に対して処理を行うコマンドでは、Character code 関数のみが特段の注意を必要とします。インタプリタモードでは、空でない文字列や空の文字列をこの関数に渡せます。 コンパイルモードでは、空の文字列を渡すことができません。Character code に、空の文字列が格納された変数を渡すと、コンパイラはコンパイル中にエラーを見つけることはできません。
SEND VARIABLE(variable) RECEIVE VARIABLE(variable)
上記2つのコマンドは変数をディスクに保存または読み込む場合に使用されます。変数が引数としてこれらのコマンドに渡されます。
コマンドに渡す変数の型は、常に同じ型でなければなりません。変数のリストをファイルに送る場合を考えてみましょう。誤ってデータ型を変えてしまう恐れを取り除くため、送信する変数のデータ型をリストの先頭で指定することをおすすめします。そうすると、これらの変数を受け取る際には、常に最初にインジケータが返されることになります。
RECEIVE VARIABLE コマンドを呼び出したら、
Case of 文を使用して、次から受け取るデータを処理できます。
例
Field (フィールドポインタ) または (テーブル番号;フィールド番号) Table (テーブルポインタ) または (テーブル番号) または (フィールドポインタ)
これら2つのコマンドは、与えられた引数によって、戻り値のデータ型が異なります。
ポインタを与えると、Table 関数は数値を返します。 数値を与えると、Table 関数はポインタを返します。 コンパイラでは、これらの関数から結果のデータ型を決定できません。このような場合は、コンパイラコマンドを使用して明確に定義してください。
Mod (value;divider) 4Dでは25を3で割った余りを求める場合、次の2通りの方法があります。
または
Variable :=25%3
コンパイラはこの2つの式を区別します。Mod 関数はすべての数値に使用できますが、%演算子は整数と倍長整数にしか使用できません。%演算子のオペランドが、倍長整数データ型の範囲を越えた場合には、返される結果は保証されません。
IDLE ON EVENT CALL (Method{; ProcessName}) ABORT
IDLE コマンドは例外処理を行うために4Dランゲージに追加されました。ON EVENT CALL コマンドを用いる場合は、必ずこのIDLE コマンドも使用してください。
このコマンドはイベント管理命令として定義することができます。
4Dのカーネルだけがシステムイベント(マウスクリックやキー操作など)を検知できます。ほとんどの場合、カーネルコールはコンパイル後のコードそのものによって起動され、ユーザに対しては透過的です。
他方、4Dがイベント待ちループなどの中でイベントの受信を待っている場合はカーネルコールがないことが明白です。
この場合、IDLE コマンドを次のように追加します。
このコマンドは、エラー処理プロジェクトメソッド内でのみ使用してください。これは4Dで使用した場合とまったく同じように動作しますが、EXECUTE FORMULA 、APPLY TO SELECTION 、APPLY TO SUBSELECTION コマンドから呼び出されたメソッド内の場合は例外です。このような状況は避けた方がよいでしょう。
コンパイラが配列のデータ型を決める際に使用する4Dコマンドは、以下の7種類です。
COPY ARRAY(source;destination) SELECTION TO ARRAY(フィールド;配列) ARRAY TO SELECTION(配列;フィールド) SELECTION RANGE TO 配列(start;end;フィールド;配列) LIST TO ARRAY(list;配列{; itemRefs}) ARRAY TO LIST(配列;list{; itemRefs}) DISTINCT VALUES(フィールド;配列)
COPY ARRAY コマンドは2個の配列型の引数を使用します。引数の一方がどこにも定義されていないと、コンパイラは定義されている方のデータ型から未定義の配列のデータ型を決定します。 この場合、以下のように処理されます。
最初の引数が定義されている場合:2番目の配列には、最初の配列のデータ型が適用されます。 2番目の引数が定義されている場合:最初の配列に2番目の配列のデータ型が適用されます。 コンパイラはデータ型を厳密にチェックするので、COPY ARRAY コマンドは同じ型の配列間で行わなければなりません。このため、整数と倍長整数と実数、あるいは、テキスト配列と文字配列で文字列の長さが一定でない場合等のように、型の似ている配列間のコピーをする際には要素を1つずつコピーする必要があります。 例えば、整数型の配列要素を実数型の配列にコピーする場合、次のように行います。
処理中に配列の次元数を変更することはできませんので、注意してください。1次元配列を2次元配列にコピーすると、エラーメッセージが出力されます。
4Dのインタプリタモードと同様、これら4つのコマンドでは配列の定義は要求されません。型が定義されていない配列にはコマンドで指定した フィールドのデータ型が割り当てられます。 例
SELECTION TO ARRAY ([MyTable]I ntField;MyArray)
"IntField"が整数フィールドの場合、"MyArray"は整数配列になります。
配列が定義されている場合は、フィールドと同じデータ型になっているかどうか確認してください。整数、倍長整数、実数は似ていますが、同じ型ではありません。 た だし、テキストや文字のデータ型では、多少許容範囲が広くなります。デフォルトにより、文字型のフィールドを使用するコマンドで配列をあらかじめ定義せず に引数として使った場合、配列に割り当てられるデフォルトのデータ型はテキストです。あらかじめ配列を文字またはテキスト型として宣言されている場合、 ユーザの指定が適用されます。
テキスト型のフィールドについても同様で、宣言された型が優先されます。SELECTION TO ARRAY 、SELECTION RANGE TO ARRAY 、ARRAY TO SELECTION 、DISTINCT VALUES コマンドは、1次元の配列でしか使用できません。SELECTION TO ARRAY コマンドにはもう1つのシンタックスがあります。SELECTION TO ARRAY(テーブル;配列). この場合、配列変数は倍長整数になります。SELECTION RANGE TO ARRAY コマンドについても同様です。
LIST TO ARRAY およびARRAY TO LIST コマンドに使用できる配列は次の2種類だけです。
このコマンドの場合、引数に使う配列をあらかじめ宣言する必要はありません。デフォルトでは、宣言されていない配列は、テキスト配列になります。配列があらかじめテキストか文字型で宣言されていない場合、ユーザの指定した型になります。
ポインタについての節で説明したように、配列を定義するコマンドの引数にポインタ参照が使われていると、コンパイラは型の矛盾を発見できません。
SELECTION TO ARRAY ([Table]Field ;Pointer->)
Pointer->が示すのが配列だとして、コンパイラは配列の型およびフィールド型をチェックすることができません。型の矛盾が起こらないようにするのは、開発者は気をつけるべきです。ポインタが示す配列を必ず定義してください。 コンパイラは、引数にポインタを使用している配列定義ステートメントを見つけると、警告メッセージを出力します。警告メッセージはこの種の矛盾を見つける際に役立ちます。
データベースで、ローカル配列(定義されたメソッド内のみで有効な配列)を使用している場合は、使用前に明確に宣言しておく必要があります。
ローカル配列を定義するには、ARRAY REAL 、ARRAY INTEGER など、配列を定義するコマンドを使用します。
例えば、プロシージャで10個の要素を持つローカルな整数配列を作る場合、次のようなコマンドを使用前に定義しておきます。
Get pointer(varName) Type (object) EXECUTE FORMULA(statement) TRACE NO TRACE
ポインタの配列を初期化する場合、配列の各要素はそれぞれ与えられた変数を表します。 例えばV1、V2、...V12というような12個の変数の場合、以下のように書くことができます。
また、以下のように書くこともできます。
この処理が終了すると、各要素が変数V1からV12を指すポインタの配列ができます。
この2つの書き方は、両方ともコンパイルできますが、他の場所で変数V1...V12の型が明らかにされていないと、コンパイラはデータ型を決定できません。そのため、このような変数は別の場所で明示的に使用するか、または定義する必要があります。 明示的に変数を定義する方法は、2通りあります。
コンパイラコマンドを使用してV1...V12を定義するには以下のように記述します。 C_LONGINT (V1 ;V2 ;V3 ;V4 ;V5 ;V6 ;V7 ;V8 ;V9 ;V10 ;V11 ;V12 )
メソッドでV1...V12に値を代入するには以下のように記述します。 V1 :=0
V2 :=0
V12 :=0
コンパイルされたデータベースの変数のデータ型は1つだけなので、この関数は不必要に思えるかも知れません。しかし、ポインタを 使用する際、この関数が役立ちます。例えば、ポインタが参照する変数のデータ型を知りたい場合、ポインタの性質上、指されているオブジェクトがわかりにく い場合があります。
EXECUTE FORMULA コマンドは、インタプリタモードでは有効ですが、コンパイルモードではその利点を活かすことができません。 コンパイルモードでは、このコマンドに引数として渡されたメソッド名は解釈されます。コンパイラのいくつかの利点を活用できない上に、引数のシンタックスチェックもできません。 また、引数にローカル変数を使用することもできません。EXECUTE FORMULA コマンドは、複数のステートメントに置き換えることができます。以下に2つの例を挙げます。
これは、以下ように書き換えることができます。
また次の例では、
ここでは、EXECUTE FORMULA コマンドをCase of に置き換えることができます。
Case of
:($Num =1)
Print1
:($Num =2)
Print2
:($Num =3)
Print3
End case
EXECUTE FORMULA コマンドは常に置き換えが可能です。実行するメソッドはデータベースのプロジェクトメソッドのリストから選択されたもので、その数には限りがあります。このため、EXECUTE FORMULA コマンドは必ずCase of 文や他のコマンドで置き換えることができます。さらに、コードの実行速度はEXECUTE FORMULA コマンドよりも速くなります。
これらのコマンドはデバッグ処理の段階で使用します。コンパイルされたデータベースでは機能しません。コンパイラはこれらのコマンドを無視するので、メソッド内に残しておいても問題ありません。
Undefined(variable) SAVE VARIABLES(document;variable1{; variable2…}) LOAD VARIABLES(document;variable1{; variable2…}) CLEAR VARIABLE(variable)
コンパイラではコンパイルモードの変数は必ず定義されます。データ型は、コンパイルが完了するまでに設定されます。このため、引数が渡されると毎回Undefined 関数はFalse を返します。
注 :アプリケーションがコンパイルモードで実行されているかどうかはIs compiled mode 関数を呼び出して確認してください。
インタプリタでは、LOAD VARIABLE コマンドの実行後にUndefined 関数を使用して変数が未定義かどうか調べることにより、ドキュメントファイルの存在の有無をチェックできます。コンパイル後はこの方法を使用できません。Undefined 関数が常にFalse を返すからです。
このテストはインタプリタでもコンパイル後でも次のようにして実行できます。
どの変数にとっても無効な値で、ロードする変数を初期化します。 LOAD VARIABLE コマンドを実行した後、ロードした変数のうちの1つを初期値と比較します。メソッドは以下のようになります。
Var1 :="xxxxxx"
Var2 :="xxxxxx"
Var3 :="xxxxxx"
Var4 :="xxxxxx"
LOAD VARIABLES ("Document";Var1 ;Var2 ;Var3 ;Var4 )
If (Var1 ="xxxxxx")
Else
End if
インタプリタモードでは、この関数には次の2つのシンタックスがあります。CLEAR VARIABLE(variable) CLEAR VARIABLE("a") コンパイル後のデータベースでは、1番目のシンタックスCLEAR VARIABLE (variable)は変数を再度初期化します(数値は0に、文字列やテキストは空にする等)。理由は、コンパイル後は未定義の変数が存在しないからです。
したがって、コンパイル後はテキスト、ピクチャ、BLOB、配列型の変数を除き、CLEAR VARIABLE コマンドで変数のメモリを解放することはできません。
配列の場合、CLEAR VARIABLE コマンドは、要素数が0の新しい配列の定義を意味します。 例えば、CLEAR VARIABLE (MyArray) において、MyArrayが整数配列の場合、以下のいずれか同じ意味を持ちます。
2番目のシンタックスCLEAR VARIABLE ("a")は、コンパイラが名前ではなくアドレスで変数にアクセスするためコンパイラで使用することはできません。
以下のコマンドには、共通する特徴が1つあります。これらのコマンドでは、最初に省略可能な引数[テーブル]があり、2番目の引数にポインタを使用することが可能な点です。
コンパイルモードでは、省略可能な[テーブル]引数を扱うことが可能です。しかし、これらのコマンドに最初に渡された引数がポインタの場合、コンパイラはポインタが何を参照しているのかわからないため、コンパイラは、最初の引数をテーブルポインタとして扱ってしまいます。
QUERY コマンドのケースで考えてみましょう。シンタックスは以下のとおりです。QUERY ({Table{;formula{;*}}) formulaの最初の要素はフィールドでなければなりません。 次のように書いた場合、
コンパイラは2番目の要素内でフィールドを表す記号を探します。しかし、“=”の記号が見つかった段階で、コンパイラは、これの関数式を判別できないため、エラーメッセージを出力します。
曖昧にならないようにするためには、以下のいずれかのように記述することができます。
QUERY (PtrTable->;PtrField->=True )
または
QUERY ([Table] ;PtrField->=True )
テーブルを省略しないことで、曖昧さを避けることができます。
ポインターを使用する際、これらのコマンドには、最初の引数が [aTable]で、2番目の引数がどちらも任意であるという共通性があります。このコンテキストでは、内部的な理由から、コンパイラーはポインターを返すコマンド(例:Current form table など)を直接引数として渡すことを許可しません(エラーが発生します)。
例えばFORM SCREENSHOT コマンドなどもこの例にあてはまります。以下のコードはインタープリタモードでは動きますが、コンパイル時に除去されます:
この場合、このコードに中継用の変数を用意してからコンパイラに渡す事ができます:
独自の4DK#リソース(定数)を作成する場合は、必ず数値の型を倍長整数(L)もしくは実数(R)に、文字列の型を(S)に設定してください。その他の型では警告メッセージが表示されます。