4Dの変数には次の3種類があります:
変数の詳細な性質についてはを参照してください。プロセス変数とインタープロセス変数はコンパイラにとって構造的に同じです。
プロセスにどの変数が使用されるか、コンパイラは知ることができないので、プロセス変数の使用にはインタープロセス変数よりも注意が必要です。新規プロセスの開始時にすべてのプロセス変数は複製されます。プロセス変数はプロセスごとに個別の値を持つことができますが、型はデータベース全体を通して同じです。
すべての変数には型があります。 データタイプ の節に記述されているとおり、変数には複数の異なる型があります:
ブール |
日付 |
倍長整数 |
グラフ |
時間 |
ピクチャ |
数値 (または実数) |
ポインタ |
テキスト |
BLOB |
オブジェクト |
配列には12の型があります:
ブール配列 |
日付配列 |
整数配列 |
倍長整数配列 |
ピクチャ配列 |
実数配列 |
時間配列 |
オブジェクト配列 |
ポインタ配列 |
BLOB配列 |
テキスト配列 |
注:
- 4D v14以降、オブジェクトという型が使用できるようになりました。
- 以前の文字(固定長文字列)型と整数型は今後変数に対しては使用されなくなりました。既存のコードにおいては、これらは自動的にテキスト型と倍長整数型へとリダイレクトされます。
インタプリタモードでは、変数は2つ以上のデータタイプを持つことが可能です。これは、コードをコンパイルするのではなく解釈する ためです。4Dはそれぞれのステートメントを別々に解釈し、そのコンテキストを理解します。しかしコンパイルモードの場合は状況が異なります。インタプリ タが一行ずつ実行処理するのに対して、コンパイルの際はデータベース全体を処理します。
コンパイラの処理方法は以下のとおりです:
- コンパイラはデータベース内のオブジェクトをシステマチックに解析します。ここでいうオブジェクトとはデータベース、プロジェクト、フォーム、トリガ、オブジェクトメソッドです。
- コンパイラはオブジェクトを調べ、データベース内で使われる各変数のデータ型を決定し、変数やメソッドのテーブル(シンボルテーブル)を生成します。
- すべての変数のデータ型が確定すると、コンパイラはデータベースの翻訳(コンパイル)を行います。ただし、各変数のデータ型が確定できなければデータベースをコンパイルすることはできません。
同 じ変数名で異なる2つのデータ型が見つかった場合、どちらか1つが優先して採用されることはありません。オブジェクトの型を設定してメモリアドレスを割り 当てるために、コンパイラはオブジェクトについての名前やデータ型などを正確に認識する必要があります。コンパイラはデータ型からそのサイズを判断しま す。コンパイルされたデータベースごとにマップが作られ、各変数の名前(もしくは識別子)、場所(もしくはメモリアドレス)、変数が占める容量(データタ イプによってわかるもの)を記録します。このマップをシンボルテーブルと呼びます。環境設定のオプションでコンパイル時にこのテーブルをファイル形式で作 成するかどうかを選ぶことができます。
このマップは、コンパイラメソッドの自動生成にも使用されます。
コンパイルで変数型を調べたりまた型定義を行ったりする場合は、簡単にコンパイラコマンドの記述場所を決めることができます。作業方法に応じて以下のいずれかの方法を選んでください:
- ローカル変数、プロセス変数、インタープロセス変数に応じて、変数が初めて使用されるメソッドやオブジェクトメソッドでコンパイラ指示子を使用します。コ ンパイラ指示子は、必ず変数が初めて使われる場所、つまり一番初めに実行されるはずのメソッドで使用するようにしてください。コンパイル時、コンパイラは 4Dで作成した順序でメソッドを処理します。エクスプローラで表示される順番ではない点に注意してください。
- コンパイラ指示子で定義するプロセス変数とインタープロセス変数は、またはから呼び出されるメソッドにまとめます。
ローカル変数については、使用するメソッドの一番初めにコンパイラ指示子をまとめてください。
コンパイラ支持しによって変数の型が決まるとき、変数はデフォルトの値を受け取り、割り当てがされない限りはセッションの間の値を保ち続けます。
デフォルトの値は、変数の型とカテゴリ、その実行コンテキスト(インタープリタかコンパイルか)に加え、コンパイルモードではデータベース設定のコンパイラーページで定義されたコンパイルオプションによって決まります:
- プロセス変数、インタープロセス変数は常に"ゼロにする"に設定されます。つまり、型によって、"0"、空の文字列、空のBlob、Nilポインター、空の日付(00-00-00)、ということです。
- ローカル変数は以下の様に設定されます:
- インタープリタモード: ゼロにする
- コンパイルモードにおいては、データベース設定のローカル変数初期化オプションによって異なります:
- "ゼロにする"が選択されている場合にはゼロになります。
- "ランダム値にする"が選択されている場合にはランダムな値に設定されます(数値ど時間については0x72677267、ブールについては常にTrue、他のものについては"ゼロにする"の場合と同じです)。
- ”なし”が選択されている場合には、(数値に関しては)ランダムな値になります。
以下の表はこれらのデフォルトの値をあらわしたものです:
型 | インタープロセス | プロセス | インタープリタモードのローカル変数 | コンパイルモードで"ゼロにする"のローカル変数 | コンパイルモードで"ランダム値にする"のローカル変数 | コンパイルモードで"なし"のローカル変数 |
ブール | False | False | False | False | True | True (場合による) |
日付による | 00-00-00 | 00-00-00 | 00-00-00 | 00-00-00 | 00-00-00 | 00-00-00 |
倍長整数 | 0 | 0 | 0 | 0 | 1919382119 | 909540880 (場合による) |
グラフ | 0 | 0 | 0 | 0 | 1919382119 | 775946656 (場合による) |
時間 | 00:00:00 | 00:00:00 | 00:00:00 | 00:00:00 | 533161:41:59 | 249345:34:24 (場合による) |
ピクチャー | ピクチャーサイズ=0 | ピクチャーサイズ=0 | ピクチャーサイズ=0 | ピクチャーサイズ=0 | ピクチャーサイズ=0 | ピクチャーサイズ=0 |
実数 | 0 | 0 | 0 | 0 | 1.250753659382e+243 | 1.972748538022e-217 (場合による) |
ポインター | Nil=true | Nil=true | Nil=true | Nil=true | Nil=true | Nil=true |
テキスト | "" | "" | "" | "" | "" | "" |
Blob | Blobサイズ=0 | Blobサイズ=0 | Blobサイズ=0 | Blobサイズ=0 | Blobサイズ=0 | Blobサイズ=0 |
オブジェクト | 未定義 | 未定義 | 未定義 | 未定義 | 未定義 | 未定義 |
コンパイラ指示子は以下の場合、有用です:
- コンパイラで前後関係から変数のデータ型を決定できない場合
- 使用目的から型を決定させたくない場合。
またコンパイラコマンドを使用するとコンパイル時間を短縮できます。
コンパイラで変数型を決定できないこともあります。このような場合、コンパイラからはエラーメッセージが出力されます。
コンパイラでデータ型を決定できない場合は、主に3つの原因があります。データ型が複数ある場合、コンパイラの推測した型があいまいな場合、そして型を判断する情報がない場合です。
データ型が複数の場合
データベース中、異なるステートメントで変数の型が変更されていると、コンパイラはエラーを生成します。
コンパイラは最初に見つけた変数を選択し、そのデータ型を同じ名前の変数の次のオカレンスに適用します。しかしその変数の型が異なるとエラーになります。
例題:
メソッドA,
Variable:=True
メソッドB,
Variable:="The moon is green"
メソッドAがメソッドBよりも先にコンパイルされると、コンパイラはステートメントVariable:="The moon is green"でデータ型が変更されていると判断します。コンパイラは型の変更が行われていることを通知し、エラーを生成します。ほとんどの場合、2番目の変数のオカレンスの名前を変更することで、問題を解決できます。
コンパイラが決定した型が曖昧な場合
コンパイラが、オブジェクトの型が正しい方ではないと推定することがあります。この場合、コンパイラ指示子を使用して、変数の型を明示的に指定する必要があります。
以下はアクティブオブジェクト用のデフォルト値を使用した例です。
フォーム内で、プロパティリストのデータソーステーマ内にあるデフォルト 値用の編集ボタンを使用して、コンボボックス、ポップアップメニュー、タブコントロール、ドロップダウンリスト、メニュー/ドロップダウンリスト、および スクロールエリアのデフォルト値を割り当てることができます(詳細は4D Design Referenceを参照)。デフォルト値は、オブジェクト名と同じ名前の配列に自動でロードされます。
オブジェクトをメソッド内で使用しない場合、コンパイラはその配列を曖昧さなくテキスト配列と推測できます。
しかし初期化を行わなければならない場合、次のようにコーディングされることがあります:
Case of
:(Form event=On Load)
MyPopUp:=2
...
End case
この場合、曖昧さが出現します。メソッドを解析する際、コンパイラはオブジェクトMyPopUpを実数型と推定します。この場合、フォームメソッドまたはコンパイラメソッドで、配列を明示的に宣言する必要があります:
Case of
:(Form event=On Load)
ARRAY TEXT(MyPopUp;2)
MyPopUp:=2
...
End case
型を判断する決め手がない場合
宣言なしに変数が使用されていて、前後関係からデータ型を決定できないような状況です。この場合、コンパイラにとっての決め手はコンパイラ指示子しかありません。
こうした状況は、主に次の4つのコンテキストにおいて起こります:
- ポインタを使用する場合
- 複数のシンタックスを持つコマンドを使用する場合
- 異なるデータ型のオプション引数を受け入れるコマンドを使用する場合
- URL経由で呼び出された4Dメソッドを使用する場合
ポインタ
ポインタは、自分自身以外のデータ型を返すことができません。
次のような場合:
Var1:=5.2(1)
Pointer:=->Var1(2)
Var2:=Pointer->(3)
(2) でPointerによりポイントされている変数の型が定義されているにもかかわらず、Var2の型を知ることはできません。コンパイル中、コンパイラはポ インタを認識できますが、ポインタが指す変数の型を知る方法はありません。結果、Var2に型を推定できません。このような場合、コンパイラ指示子が必要 です: C_REAL(Var2).
複数シンタックスコマンド
Year of関数に割り当てられた変数を使用する際、この関数の動作に基づき、変数の型は日付しかありえません。しかしことは常にそのように単純とは限りません。たとえば:
GET FIELD PROPERTIES コマンドは2つのシンタックスを受け入れます:
GET FIELD PROPERTIES(tableNo;fieldNo;type;length;index)
GET FIELD PROPERTIES(fieldPointer;type;length;index)
複数シンタックスコマンドを使用する際、コンパイラは選択されたシンタックスや引数を推測できません。データベースのどこかでその使用に基づく型付けが行われていない限り、コンパイラ指示子を使用して変数を型付けしなければなりません。
異なるデータ型のオプション引数を受け入れるコマンド
異なるデータ型の複数のオプション引数を受け入れるコマンドを使用する場合、コンパイラはどのオプション引数が使用されたか知ることができません。例えば:
GET LIST ITEM コマンドは2つのオプション引数を受け入れます; 1番目は倍長整数で2番目はブールです。
コマンドは以下のいずれかの方法で使用されます:
GET LIST ITEM(list;itemPos;itemRef;itemText;sublist;expanded)
または:
GET LIST ITEM(list;itemPos;itemRef;itemText;expanded)
データベースのどこかでその使用に基づく型付けが行われていない限り、コンパイラ指示子を使用して変数を型付けしなければなりません。
URLで呼ばれるメソッド
URLから呼ばれる必要のある4Dメソッドを書くときで、メソッドで$1を使用しないときでも、以下のように明示的に$1をテキスト変数として宣言しなければなりません:
C_TEXT($1)
実際コンパイラは4DがURLから呼ばれるかどうか判断できません。
データベースで使用する変数がすべて明示的に定義されていれば、コンパイラで型定義を調べる必要はありません。この場合、オプションを設定してメソッドの翻訳フェーズだけを行うように指定できます。この操作により、コンパイル時間を半分以下に短縮できます。
コンパイラコマンドを使用することで、メソッドの処理速度を上げることができます。この件についての詳細は最適化のヒント の節を参照してください。簡単な例として、カウンタとして使用するローカル変数をインクリメントする必要があるとします。倍長整数として宣言すると、コンパ イルしたデータベースの効率が良くなります。例えばWindowsの場合、実数データがメモリを8バイト使用するのに対し、倍長整数にすると、4バイトし か使用しません。8バイトのカウンタをインクリメントする場合は当然、4バイトの場合より時間がかかります。
コンパイラ指示子は、コンパイラに変数の型付けをまかせるかどうかによって以下2通りに処理方法が異なります。
コンパイラは変数の判別基準を守り、以下の方法で型を設定します。
2つの可能性があります。
- 変数の型が設定されていない場合、自動的にコンパイラが代わりにタイプを設定します。曖昧でない場合は可能な限り、使用目的から変数型を設定します。例えば:
V1:=True
コンパイラは変数V1をブール型と決定します。
同様に次のように書くと:
V2:="This is a sample phrase"
コンパイラは変数V2をテキスト型と決定します。
また、上の例ほど明確でない場合でも、コンパイラは以下のように変数のデータ型を設定することができます:
V3:=V1
V4:=2*V2
また、4Dのコマンドやメソッドに対する呼び出しからも、コンパイラは変数のデータ型を決定します。例えばブール型と日付型の引数をメソッドに渡した場合、コンパイラは呼び出されたローカル変数$1および$2にブール型と日付型を割り当てます。
推測からデータ型が決定される場合、環境設定で指定されていない限りは整数、倍長整数、文字列のような制限のあるデータ型が割り当てられることはありません。デフォルトとして常に最も広範囲な型が割り当てられます。例えば:
Number:=4
と記述した場合、ここでは4が整数であっても他の状況では4.5になる可能性もあるので、Numberには実数型が割り当てられます。
変数の型を整数、倍長整数または文字列にする場合は、コンパイラ指示子を使います。これらのデータ型はメモリ占有率が少ないため、処理速度が早くなります。
すでに変数型を設定済みで、定義の整合性も完全であると確信した場合、コンパイラの環境設定を使用して、コンパイラに型の自動決定を行わないようコ ンパイラに指示することができます。定義が徹底されておらず、不完全な場合、コンパイル終了時にエラーメッセージが表示され、必要な変更を行うよう求めら れます。 - コンパイラ指示子を使用すると、データベースで使用される変数の型を明示的に定義できます。使用方法は次の通りです:
C_BOOLEAN(Var)
このような指示子を通じて、コンパイラにブール型の変数を作成するよう通知できます。
アプリケーションでコンパイラコマンドが使用されていれば、コンパイラが型を推測するという作業をしなくて済みます。
コンパイラ指示子は、代入や用途から得られた結果より優先されます。
コンパイラ指示子C_INTEGERで定義した変数は、実際にはC_LONGINTで定義したものと同じです。これらは実際には、-2147483648から+2147483647までの倍長整数です。
コンパイラに型定義をチェックさせたくない場合、コンパイラ指示子を識別できるようなコードをコンパイラに与える必要があります。
これを行う方法は以下です:
プロセス変数、インタープロセス変数についてのコンパイラ指示子および引数を、名前の先頭がキーワードCompilerで始まる1個あるいは複数個のメソッドに記述します。デフォルトで、コンパイラに5種類のコンパイラメソッドを自動生成させ、変数、配列、メソッド引数ごとに命令をまとめることができます(詳細はDesign Referenceマニュアルを参照)。
Note: 引数定義のためのシンタックスは次のとおりです:
Directive (methodName;parameter). このシンタックスをインタプリタモードで実行することはできません。
特別な引数
- データベースメソッドが受け取る引数 これらの引数が明確に定義されていなければ、コンパイラが型を決定します。定義する場合は、そのデータベースメソッド内で行わなければなりません。この引数定義をCompilerメソッド内に記述することはできません。
例:は6つのテキスト引数$1から$6までを受け取ります。データベースメソッドの最初に、C_TEXT($1;$2;$3;$4;$5;$6)を記述する必要があります。 - トリガ
トリガの結果である引数$0(倍長整数)は、引数が明確に定義されていなければ、コンパイラが型を決定します。定義する場合は、トリガ自身の中で行う必要があります。この引数定義は、Compilerメソッド内には記述できません。 - "On Drag Over"フォームイベントを受け入れるオブジェクト
"On Drag OVer"フォームイベントの結果である引数$0(倍長整数)は、引数が明確に定義されていなければ、コンパイラが型を決定します。定義する場合は、オブジェクトメソッドの中で行う必要があります。この引数定義は、Compilerメソッド内には記述できません。
Note: コンパイラは引数$0を初期化しません。したがって、On Drag Overフォームイベントを使用したら、直ちに"$0"を初期化しなければなりません。例えば:
コンパイラ指示子によって、曖昧なデータ型は除外されます。特定の厳密さは要求されますが、コンパイラが全ての不一致を受け入れないというわけではありません。
例えば整数と定義した変数に実数値を代入すると、コンパイラはこれを型の不一致と見なさず、コンパイラ指示子に応じた値を代入します。以下のように記述した場合:
C_LONGINT(vInteger)
vInteger:=2.6
コンパイラはこれを型の矛盾としては扱わず、したがってコンパイルは可能です。そして代わりに数値の小数部分を切り上げます(2.6ではなくて3になります)。