この記事では、InterSystems Cachéにおけるマクロについて説明します。 マクロは、コンパイル中に一連の命令に置き換えられるシンボリック名です。 マクロは、渡されたパラメーターとアクティブ化したシナリオに応じて、呼び出されるたびに一連の命令セットに「展開」されます。 これは、静的コードの場合もあれば、ObjectScriptを実行して得られる結果である場合もあります。 それでは、アプリケーションでマクロをどのように使用できるのかを見てみましょう。
/// #Define Macro[(Args)] [Value]
#define HW Write "Hello, World!"後は、$$$HW(マクロを呼び出す$$$と、その後にマクロ名を指定)を記述するのみです。
ClassMethod Test()
{
#define HW Write "Hello, World!"
$$$HW
}
これは、コンパイル中に次のINTコードに変換されます。
zTest1() public {
Write "Hello, World!" }
このメソッドが呼び出されると、ターミナルに次のテキストが表示されます。
Hello, World!_例2_ 次の例では、変数を使用し見ましょう。
ClassMethod Test2()
{
#define WriteLn(%str,%cnt) For ##Unique(new)=1:1:%cnt { ##Continue
Write %str,! ##Continue
}
$$$WriteLn("Hello, World!",5)
}
上記のコードでは、%str文字列が%cnt回書き込まれます。 変数名は%で始まる必要があります。 [##Unique(new)](http://docs.intersystems.com/latestj/csp/docbook/DocBook.UI.Page.cls?KEY=GCOS_macros#GCOS_macros_mpp_lblbUnique) コマンドで、生成されたコードに新しい一意の変数を作成し、[##Continue](http://docs.intersystems.com/latestj/csp/docbook/DocBook.UI.Page.cls?KEY=GCOS_macros#GCOS_macros_mpp_lblbContinue)によって、次の行にマクロの定義が続くことを示します。 このコードは、次のINTコードに変換されます。
zTest2() public {
For %mmmu1=1:1:5 {
Write "Hello, World!",!
} }
ターミナルには次のように表示されます。
Hello, World! Hello, World! Hello, World! Hello, World! Hello, World!
_例3_ より複雑な例に進みましょう。 [ForEach](https://ja.wikipedia.org/wiki/Foreach%E6%96%87)演算子は、グローバルを反復処理する上で非常に役立ちます。それでは作成してみましょう。
ClassMethod Test3()
{
#define ForEach(%key,%gn) Set ##Unique(new)=$name(%gn) ##Continue
Set %key="" ##Continue
For { ##Continue
Set %key=$o(@##Unique(old)@(%key)) ##Continue
Quit:%key=""
#define EndFor }
Set ^test(1)=111
Set ^test(2)=222
Set ^test(3)=333
$$$ForEach(key,^test)
Write "key: ",key,!
Write "value: ",^test(key),!
$$$EndFor
}
INTコードでは次のようになります。
zTest3() public {
Set ^test(1)=111
Set ^test(2)=222
Set ^test(3)=333
Set %mmmu1=$name(^test)
Set key=""
For {
Set key=$o(@%mmmu1@(key))
Quit:key=""
Write "key: ",key,!
Write "value: ",^test(key),!
} }
これらのマクロでは何が起こっているのでしょうか。
1. グローバルの名前を新しい%mmmu1変数に書き込みます([$name](http://docs.intersystems.com/latestj/csp/docbook/DocBook.UI.Page.cls?KEY=RCOS_fname)関数)。
2. キーは、初期の空の文字列値です。
3. 反復サイクルが開始します。
4. [間接演算子](http://docs.intersystems.com/latestj/csp/docbook/DocBook.UI.Page.cls?KEY=GCOS_operators#GCOS_operators_indirection)と[$order](http://docs.intersystems.com/latestj/csp/docbook/DocBook.UI.Page.cls?KEY=RCOS_forder)関数を使って、キーに次の値が割り当てられます。
5. キーが""値を取っているかどうかを、[事後条件](http://docs.intersystems.com/latestj/csp/docbook/DocBook.UI.Page.cls?KEY=GCOS_commands#GCOS_commands_pc)を使ってチェックします。取っている場合は反復が完了し、サイクルが終了します。
6. 任意のユーザーコードが実行されます。この場合、キーと値が出力されます。
key: 1 value: 111 key: 2 value: 222 key: 3 value: 333[%Collection.AbstractIterator](http://docs.intersystems.com/latest/csp/documatic/%25CSP.Documatic.cls?PAGE=CLASS&LIBRARY=%25SYS&CLASSNAME=%25Collection.AbstractIterator)クラスから継承したリストと配列を使用している場合は、同様のイテレーターを記述できます。
_例4_ マクロにはさらに、コンパイル段階で任意のObjectScriptコードを実行し、マクロの代わりにその結果に置き換えるという別の機能があります。 コンパイル時間を示すマクロを作成してみましょう。
ClassMethod Test4() { #Define CompTS ##Expression("""Compiled: " _ $ZDATETIME($HOROLOG) _ """,!") Write $$$CompTS }これは、次のINTコードに変換されます。 zTest4() public { Write "Compiled: 18.10.2016 15:28:45",! } このメソッドが呼び出されると、ターミナルには次の行が表示されます。
Compiled: 18.10.2015 15:28:45[##Expression](http://docs.intersystems.com/latestj/csp/docbook/DocBook.UI.Page.cls?KEY=GCOS_macros#GCOS_macros_mpp_lblbExpression)は、コードを実行して結果を置き換えます。 入力には、ObjectScript言語の次の要素を使用できます。 * 文字列: "abc" * ルーチン: $$Label^Routine * クラスメソッド: ##class(App.Test).GetString() * COS関数: $name(var) * 上記の要素の任意の組み合わせ _例5_ コンパイル時に、ディレクティブの後に続く式の値に応じてソースコードを選択するには、プリプロセッサディレクティブの[#If、#ElseIf、#Else、#EndIf](http://docs.intersystems.com/latestj/csp/docbook/DocBook.UI.Page.cls?KEY=GCOS_macros#GCOS_macros_mpp_lbIf)を使用します。 たとえば、次のメソッドがあるとします。
ClassMethod Test5()
{
#If $SYSTEM.Version.GetNumber()="2016.2.0" && $SYSTEM.Version.GetBuildNumber()="736"
Write "You are using the latest released version of Caché"
#ElseIf $SYSTEM.Version.GetNumber()="2017.1.0"
Write "You are using the latest beta version of Caché"
#Else
Write "Please consider an upgrade"
#EndIf
}
Cachéバージョン2016.2.0.736では、このメソッドは次のINTコードにコンパイルされます。
zTest5() public { Write "You are using the latest released version of Caché" }ターミナルには次のように表示されます。
You are using the latest released version of CachéベータポータルからダウンロードしたCachéを使用している場合、コンパイルされたINTコードは異なります。
zTest5() public {
Write "You are using the latest beta version of Caché"
}
ターミナルには次のように表示されます。
You are using the latest beta version of Caché古いバージョンのCachéは、次のようにプログラムの更新を提案するINTコードをコンパイルします。 zTest5() public { Write "Please consider an upgrade" } ターミナルには次のように表示されます。
Please consider an upgradeこの機能は、クライアントアプリケーションで古いバージョンと新しいバージョンとの互換性を保証したい場合に、Cachéの新機能が使用される可能性があるときなどに役立ちます。 プリプロセッサディレクティブの[#IfDef](http://docs.intersystems.com/latestj/csp/docbook/DocBook.UI.Page.cls?KEY=GCOS_macros#GCOS_macros_mpp_lbIfDef)と[#IfNDef](http://docs.intersystems.com/latestj/csp/docbook/DocBook.UI.Page.cls?KEY=GCOS_macros#GCOS_macros_mpp_lbIfNDef)は、順にマクロの存在と不在を検証することで、同じ目的を果たすことができます。