【IRIS/Cache】オリジナルの$z関数を作ろう!(%ZLANGF00)

本記事は、「%ZLANGF00」ルーチンを利用して、オリジナル$z関数の作成方法をご紹介します。

※この記事は下記の方向けになります。
  • オリジナルの$z関数を作成したい方

はじめに

「共通関数を実行する際、クラス名.関数名()で実行すると冗長的だな」とか「スーパークラスに組み込むと煩雑になるな」とか思ったことはありませんか?

そんな時は、オリジナルの$z関数を作成してみるのも一興です。

この記事では、%ZLANGF00ルーチンの概要、活用方法、注意点について具体的に解説していきます。

%ZLANGF00とは

「%ZLANGF00」ルーチンは、3つある「%ZLANG」ルーチンシリーズの1つになります。

関数のFunctionの頭文字「F」をルーチン名に冠している様に、オリジナルの$z関数を設定する事ができます。

ベース作成

先ずは新規ルーチンの名前を「%ZLANGF00.mac」とし、下記を貼り付けてください。

%ZLANGF00	;
	q
	;-
	;

これで一先ずベースは完了です。
次は、オリジナルの$z関数を作成しましょう。

オリジナルの$z関数を作成する

では、オリジナルの$z関数を作成したいと思います。

今回作ろうと考えているのは、$horologの値を「YYYY/MM/DD」形式に変換する関数にしたいと思います。

割とこの日付形式は利用される割には、$ZDATEのdformatに候補が無いんですよね。
無いのであれば、この際作成しちゃいましょう!

サンプルは下記になります。

%ZLANGF00	;
	q
	;-
	;
ZSDATE(h) public {
	q $tr($zd(+h, 3),"-", "/")
}

やっている事は、「YYYY-MM-DD」に変換して「-」を「/」に$TRANSLATEしているだけです。

では、ターミナルで動作を確認してみましょう。
ネームスペースはいつもの「SAMPLE」で行いたいと思います。

$horologの値を引数とし、「YYYY/MM/DD」に変換された事を確認しました。

では、「USER」ネームスペースではどうでしょうか?

いいですね!
10日前の日付を「YYYY/MM/DD」形式で出力する事が出来ました。

簡単な関数ですが、オリジナルの$z関数を作成する事ができました。
便利な関数等をオリジナル%z関数にする事で、全体のコーディング量を減らすことが可能になると思います。

ただし、注意が1点あります。

同一のインスタンスで他社システムと相乗りする場合、同じ「$LANGF00」ルーチンも相乗りで記述する事になります。
関数の名称が被る事だけは注意が必要になります。

処理速度を検証する

例えコーディング量が減ったとしても、処理が異常に遅くなってしまっては本末転倒です。

通常の処理とオリジナル関数とで、処理速度の差を検証してみましょう。

検証してみる

同じ処理を関数化して検証してみます。

ClassMethod cnvDate(h As %Date) As %String
{
	q $tr($zd(h, 3),"-", "/")
}

下記をターミナルに張り付けて速度検証を行ってみます。

Check(cnt)	;
	s start=$zh
	f pos=1:1:cnt {
		s d=$zsdate($h)
	}
	w "オリジナル:"_($zh-start),!
	
	// 通常の関数 
	s start=$zh
	f pos=1:1:cnt {
		s d=##class(developer.Sample).cnvDate(+$h)
	}
	w "   通常:"_($zh-start),!

では、下記コマンド実行して検証開始です。

d Check(1000000)

【実行結果(100万回ループ)】
オリジナル:3.059877
   通常:2.495885

えぇ!? 遅せぇ?

コントみたいな落ちになってしまいました。

ドキュメントにある下記記載はこの事を指すんですねぇ・・・

^%ZLANG 機能の実行速度は標準の InterSystems IRIS 機能ほど速くありません。
パフォーマンスが重要なルーチンをコーディングする際には、この点を考慮してください。

んー・・・実行回数から見たら些細な差ですが、どう判断したものか(汗

続・検証してみる

処理が遅いのは認識しました。

では、次は、「呼び出し」が遅いのか、「処理自体」が遅いのか切り分けたいと思います。

両者を下記修正して検証です。
 ※developer.Sample.clsも同様の処理を行いました。

ZSDATE(cnt) public {
	s h = $h
	s start = $zh
	f pos=1:1:cnt {
		s val =  $tr($zd(h, 3),"-", "/")
	}
	q ($zh - start)
}

では、改めて検証です。

Check2(cnt)	;
	w "オリジナル:"_$zsdate(cnt),!
	w "   通常:"_##class(developer.Sample).cnvDate(cnt),!

では、下記コマンド実行して検証開始です。
今回は、1,000万回のループで確認してみます。

d Check2(10000000)

【実行結果(1,000万回ループ)】
オリジナル:2.669659
   通常:2.767437

1,000万回の実行で0.1秒の差であれば、誤差と言っても過言ではないですね。
何回か繰り返しても、結果はあまり変わりません。

検証結果からみると、「%LANGF00」ルーチンの呼び出しに時間が掛かっているようです。
コーディングが楽になる代わりに、呼び出し時間に僅かな時間差がでる・・・う~ん、悩ましいですね。

おわりに

いかがだったでしょうか。
今回は、オリジナルの$z関数の自作という、夢のような機能のご紹介でした。

ただ、関数の呼び出し時間が、通常の関数より若干遅いという弱点があります。
ひたすらに速度を追い求める様なシステムであれば、相性が悪いでしょう。

また、他社とのシステム相乗り時にも注意が必要です。

ただ、それらを乗り越えた先に、ロマン溢れるオリジナル関数が待っています!

%ZLANGF00ルーチンを活用して、効率の良いコーディングを目指してみませんか?