CachéDBMSで1次関数の類似物を探しています

この投稿は、 Caché宣言的開発の記事に加えて書かれています



[2, 3, 5, 7, 11, 13, 17].forEach(function(i) { console.log(i); });
      
      





COSを使用してCachéでこれを行う方法

カットの下で、特定のトピックに関するいくつかの演習。



Cachéに組み込まれているサーバー言語の1つであるCOSが、同じ簡潔で明確かつ柔軟なコードをどのように実現できるかを確認するために、独自のtest.ForEachクラスはリストコレクションを操作するために開発されました。

クラスtest.ForEachのソースコード
///コレクションのクラスイテレータ。

クラスtest.ForEach Extends%RegisteredObject [ Final ]

{

///あらゆるタイプのコレクションリスト<s>ほとんど</ s>。

プロパティ コレクション As%Collection.AbstractList [ Internal Private ReadOnly Transient ];

/// <property>コレクション</ property>プロパティの初期化。

/// <br> <br>有効な引数<var> val </ var>:

/// <br> <li>%Collection.AbstractList;から派生したクラスのオブジェクト。

/// <br> <li> $ Listの形式の単純な要素のリスト。

/// <br> <li>文字列形式の単純な要素のリスト。 この場合、<var> sep </ var>は文字列内の要素の区切り文字です。

メソッド %OnNew( val sep = "、" As%Status [ Private ServerOnly = 1]

{

if $ IsObject val {

終了 : ' val %Extends "%Collection.AbstractList" $$$エラー $$$ OrefInvalid val

i%コレクションを 設定 = val

} else {

i%コレクション= ##クラス %ListOfDataTypes )を設定します。 %新規 ()

.. コレクションを 行い ます InsertList $ select $ listvalid val ): val 、1: $ listfromstring val sep )))

}

$$$を終了OK

}

///メインメソッドハンドラー。

/// <br>

/// <br>引数:

/// <br>

/// <br> <var> func </ var>:<ol> <li>クラスインスタンスメソッド名</ li> <li>クラスメソッド名(any)</ li> <li>コマンド形式のコード< link href = / DocBook.UI.Page.cls?KEY = RCOS_cxecute> xecute </ link> </ li> <li>短縮コマンド</ li> </ ol>

///呼び出し例:<example>

/// s obj = ## class(test.ForEach)。%New( "2,3,5")

///; コレクションの各要素に対して、対応するクラスメソッドが引数を渡して呼び出されます。

///; 最初の引数は出力/入力で、残りは入力ですが、これは合意の方法にすぎません。

///; 必要に応じて、それらを交換したり、数日間休んだりすることができます。

/// d obj.Do( "className:methodName" ,. result、param1、param2、paramN)

///; 要素の合計(数値のコレクションに対してのみ意味があります)

/// d obj.Do( "+"、。result)

///; 製品(数字のコレクションに対してのみ意味があります)

/// d obj.Do( "*"、。result)

///; 区切り文字の連結(単純型のコレクションでのみ意味があります)

/// d obj.Do( "_"、。result、separator)

///; 最小(単純型のコレクションに対してのみ意味があります)

/// d obj.Do( "min" ,. result)

///; 最大(単純型のコレクションに対してのみ意味があります)

/// d obj.Do( "max" ,. result)

///; 平均(数値のコレクションに対してのみ意味があります)

/// d obj.Do( "avg" ,. result)

///; el =コレクションの要素、args =引数が渡されるコード

/// d obj.Do($ lb( "s args(1,1)= args(1,1)+ el")、。result); 同等の「+」

///; サブルーチンsub ^ progと引数の受け渡し

/// d obj.Do($ lb( "d sub ^ prog(el、args ...)")、。result、param1、param2、paramN)

/// </ example>

///

メソッド Do( func = "+" Args ... As%Status

{

#define ReturnOnError(%expr) s sc =%expr ret:$$$ ISERR sc sc



quit : '.. コレクション カウント () $$$ OK



func = "+" {

set func = $ listbuild "s args(1,1)= args(1,1)+ el"

} elseif func = "*" {

set func = $ listbuild "s args(1,1)= args(1,1)* el"

} elseif func = "_" {

set func = $ listbuild "s args(1,1)= args(1,1)_args(1,2)_el"

} elseif func = "min" {

set func = $ listbuild "s:el <args(1,1)args(1,1)= el" )、 Args (1)= 999999999999999

} elseif func = "max" {

set func = $ listbuild "s:el> args(1,1)args(1,1)= el" )、 Args (1)=-999999999999999

} elseif func = "avg" {

set func = $ listbuild "s args(1,1)= el / args(1,2)+ args(1,1)" )、 Args = 2、 Args (2)= .. collection カウント () キル Args (1)

}



if $ listvalid func {

set cmd = $ list func



$$$ ReturnOnError ##クラス %ルーチン 。CheckSyntax "" _ cmd ))



set cmd = "(el、args ...){" _ cmd _ "}"



キーを 設定 = ""

{

el = .. collectionを 設定し ます GetNext (。 キー

quit key = ""

xecute cmd el 。Args

}

} else {

if func [ ":" {

set className = $ piece func ":" 、1)

set methodName = $ piece func ":" 、2)

quit : ' ##クラス %Dictionary.MethodDefinition )。 IDKEYExists className methodName $$$エラー $$$ MethodDoesNotExist func

quit : ' $$$ defMemberKeyGet className "m" methodName 、23) $$$ ERROR $$$ GeneralError $$$ FormatText 「Method%1はメソッド%2のメソッドで ありません methodName className ))

キーを 設定 = ""

{

el = .. collectionを 設定し ます GetNext (。 キー

quit key = ""

$$$ ReturnOnError $ classmethod className methodName el 。Args ))

}

} else {

set methodName = func

キーを 設定 = ""

{

el = .. collectionを 設定し ます GetNext (。 キー

quit key = ""

set className = $ classname el

return : ' ##クラス %Dictionary.MethodDefinition )。 IDKEYExists className methodName $$$エラー $$$ MethodDoesNotExist className _ ":" _ methodName

return $$$ defMemberKeyGet className "m" methodName 、23) $$$ ERROR $$$ GeneralError $$$ FormatText 「Method%1 is not a instance method of class%2」 methodName className ))

$$$ ReturnOnError $メソッド el methodName ,. Args ))

}

}

}



$$$を終了OK

}

/// <example> d ## class(test.ForEach).Test()</ example>

ClassMethod テスト()[ 内部 ]

{

set old = $ system .Process 未定義 (2)

{

; ===============================単純なデータタイプの収集============== ===============

t = ##クラス test.ForEach )を設定します。 %新規 "2,3,5"

; s t = ## class(test.ForEach)。%New( "2,3,5、asd")

; s t = ## class(test.ForEach)。%New(## class(test.ForEach)。%New()); コメントを解除してエラーを表示します

if ' $ IsObject t $$$ ThrowStatus %objlasterror



書き込み !、 "==========" 、!、 "test.myclass:Dump" 、!!!

$$$ ThrowOnError t。Do "test.myclass:Dump" ))

; または$$$ ThrowOnError(t.Do( "test.myclass:Dump" ,. result))



write !、 "==========" 、!、 "test.myclass:Dump(.r =" "result" "、" "p1" "、" "p2" ")" !! !

set r = "result" $$$ ThrowOnError t。Do "test.myclass:Dump" ,. r "p1" "p2" ))



書き込み !、 "==========" 、!、 "test.myclass:Sum(.r)" 、!!!

$$$ ThrowOnError t。Do "test.myclass:Sum" ,. R )) write "Result =" r 、!

; $$$ ThrowOnError(t.Do( "test.myclass:Sum" ,. R、5)); コメントを解除してエラーを表示します



!、 「==========」 、!、 「+ 10」 、!! r = 10に 設定

$$$ ThrowOnError t。Do 、。 R )) write "Result =" r 、!

「==========」 「+」 、!! Rを 殺す

$$$ ThrowOnError t。Do 、。 R )) write "Result =" r 、!

「==========」 、!、 「*」 、!! r = 1に 設定

$$$ ThrowOnError t。Do "*" 、。 R )) write "Result =" r 、!

書き込み !、 "==========" 、!、 "_ + delimiter =" "^" "" !! Rを 殺す

$$$ ThrowOnError t。Do "_" 、。 R "^" )) write "Result =" r 、!



書き込み !、 "==========" 、!、 "min(入力引数は考慮されません)" 、!!!

set r = "asd" $$$ ThrowOnError t。Do "min" 、。 r )) write "Result =" r 、!

write !、 "==========" 、!、 "max(入力引数は考慮されません)" 、!!!

set r = "asd" $$$ ThrowOnError t。Do "max" 、。 r )) write "Result =" r 、!

書き込み !、 "==========" 、!、 "avg(入力引数は考慮されません)" 、!!!

set r = "asd" $$$ ThrowOnError t。Do "avg" 、。 r )) write "Result =" r 、!



書き込み !、 "==========" 、!、 "s args(1,1)= args(1,1)+ el" 、!!!

kill r $$$ ThrowOnError t。Do $ listbuild "s args(1,1)= args(1,1)+ el" 、。 r )) write r 、!



write !、 "==========" 、!、 "d sub ^ prog(el、args ...)[.r =" "r" "、" "p1" "、" "p2 「」]「 !!!

set r = "r" $$$ ThrowOnError t。Do $ listbuild "d sub ^ prog(el、args ...)" 、。 r "p1" "p2" ))

; ===============================複雑なデータ型の収集============== ===============

set list = ## class %ListOfObjects )。 %新規 ()

for i = "f1" "f2" "f3" do list 挿入 ##クラス test.myclass )。 %新規 i ))

; f i = "f1"、 "f2"、 "f3"、7 d list.Insert(## class(test.myclass)。%New(i))



t = ##クラス test.ForEach )を設定します。 %新規 リスト

if ' $ IsObject t $$$ ThrowStatus %objlasterror



「++++++++++」 、!、 「test.myclass:Dump」 、!!!

$$$ ThrowOnError t。Do "test.myclass:Dump" ))



!、 「++++++++++」 、!、 「PrintLn」 、!!!

$$$ ThrowOnError t。Do "PrintLn" ))



!、 "++++++++++" 、!、 "PrintLn(、" "Element =" ")" 、!!!

$$$ ThrowOnError t。Do "PrintLn" ,, "Element =" ))



!、 「++++++++++」 、!、 「Concat(.r)」 、!! Rを 殺す

$$$ ThrowOnError t。Do "Concat" ,. R )) write "Result =" r 、!

; $$$ ThrowOnError(t.Do( "Concat" ,. R、 "f3"))w "Result ="、r、! ; コメントを解除してエラーを表示します

write !、 "++++++++++" 、!、 "SetField(、" "blablabla" ")+ PrintLn(、" "Element =" ")" 、!!!

$$$ ThrowOnError t。Do "SetField " ,, "blablabla" )) $$$ ThrowOnError t。Do "PrintLn" ,, "Element =" ))



書き なさい!、 「++++++++++」 、!、 「d el.PrintLn(.args)」 、!!!

$$$ ThrowOnError t。Do $ listbuild "d el.PrintLn(.args)" )))



書き ます!、 「++++++++++」 、!、 「w」「field = "」、el.field 、!」 !!!

$$$ ThrowOnError t。Do $ listbuild "w" "field =" "、el.field、!" )))

} catch ex {

#dim ex As %Exception.AbstractException

元を 書き ます。 DisplayString ()

}

$ system .Processを実行し ます。 未定義 古い

}

}



クラスコードは、COS機能の一部を使用しました。





注意! 以下の例はすべて、 未定義 = 2であると仮定しています。



このモードは端末で設定できます。

 > set old=$system.Process.Undefined(2)
      
      





テストを実行し、それらを元の場所に戻すことを忘れないでください

 > do $system.Process.Undefined(old)
      
      







test.myclassクラスのソースコード
クラスtest.myclass Extends%RegisteredObject

{

///文字列フィールド。

プロパティ フィールド。

/// <property>フィールド</ property>プロパティの初期化。

メソッド %OnNew( field As%Status [ Internal Private ServerOnly = 1]

{

set .. field = field

$$$を終了OK

}

/// <property>フィールド</ property>に最初の<u>入力</ u>引数を入力します。

メソッド SetField( Args ... As%Status

{

set .. field = Args (1,2)

$$$を終了OK

}

/// <property>フィールド</ property>および最初の<u>入力</ u>引数を出力します。

メソッド PrintLn(引数 ... As%ステータス

{

Args (1,2)、 $$$ quot (.. field 、!

$$$を終了OK

}

/// <property>フィールド</ property>とセパレ​​ーターの連結(<span style = "color:green;"> <b>インスタンス</ b>クラスメソッド</ span>)。

/// <br>最初の入力引数が<var>フィールド</ var>と一致する場合、エラーを生成します(デモンストレーションのために<span style = "color:red;">!</ span>)

メソッド 連結( 引数... As%ステータス

{

set Args (1,1)= Args (1,1)_ Args (1,2)_ .. フィールド

quit $ select (.. field = Args (1,2): $$$ ERROR $$$ GeneralError $$$ FormatText "エラーが要素で発生しました:%1" 、.. field ))、1: $$ $ OK

}

/// Sum <var> elem </ var>(<span style = "color:green;">クラスメソッド</ span>)。

/// <br>最初の<u>入力</ u>引数が<var> elem </ var>(別名<property>フィールド</ property>)と一致する場合、エラー(<span style = "color:赤; ">デモ用!</ span>)

ClassMethod Sum( elem Args ... As%ステータス

{

Args (1,1)= Args (1,1)+ elemを設定します

quit $ select elem = Args (1,2): $$$エラー $$$ GeneralError $$$ FormatText "要素でエラーが発生しました:%1" elem ))、1: $$$ OK

}

///すべての引数を出力します。

/// <br> <br> <var> elem </ var> =コレクションアイテム

/// <br> <var> Args </ var>(1)=最初を除いて渡された引数の数、つまり <var> elem </ var>

/// <br> <var> Args </ var>(1,1)= argument 1(<span style = "color:red;">この入力/出力引数があります</ span>)

/// <br> <var> Args </ var>(1,2)=引数2

/// <br> ...

/// <br> <var> Args </ var>(1、n)=引数n

ClassMethod Dump( elem Args ... As%ステータス

{

params = ""を 設定します



for i = 2:1: Args 1) set params = params _ $ listbuild Args (1、 i ))

if ' $ IsObject elem {

el = elemを 設定し ます

} elseif elem %Extends "test.myclass" {

el = elemを 設定し ます 野原

} else {

el = elemを 設定し ます %ClassName $$$ YES

}

write "Element =" $$$ quote el )、 "、Output argument =" $$$ quote Args (1,1))、 "、Additional arguments =" $$$ quote $ listtostring params ))、!

$$$を終了OK

}

}



prog.macのソースコード
#include %systemInclude



sub (el、args ...) public {

「--------」 、!、 「el = " $$$クォート el 、!

zwrite 引数

書き ます!

}





行こう!

ForEachオブジェクトの初期化

初期化はtest.ForEach。%New(val、sep)メソッドを使用して実行されます

最初のパラメーターvalは、リテラルのコレクション(リストまたはオブジェクトのコレクション)を取ります。

2番目のsepパラメーターは、リテラルコレクションの区切り文字です。



1.リテラルのコレクションの初期化



 set tmp=##class(test.ForEach).%New("2,3,5")  set tmp=##class(test.ForEach).%New($listbuild(2,3,5))
      
      







2.任意のセパレーターを介したリテラルのコレクションの初期化

たとえば、セパレーター「;」を介して



 set tmp=##class(test.ForEach).%New("2;zxc;5;asd,ert",";")  set tmp=##class(test.ForEach).%New($listbuild(2,"zxc",5,"asd,ert"))
      
      







3.オブジェクトのリストの初期化

 set list=##class(%ListOfObjects).%New() for i="f1","f2","f3",7 do list.Insert(##class(test.myclass).%New(i)) set tmp=##class(test.ForEach).%New(list)
      
      







注意! %Newメソッドのtest.ForEachクラスは、 %Collection.AbstractListから継承されたコレクションを必要とします



使用例



test.myclassクラスは、コレクション内の各要素に対して呼び出すいくつかのメソッドを実装します。

たとえば、Dump-要素と渡されたパラメーターに関する情報を表示します。

Sum-引数を合計し、結果を表示します。



コレクションの例

コレクションを初期化します。

 set tmp=##class(test.ForEach).%New("2,3,5")
      
      







ターミナルで実行します。

 >do tmp.Do("test.myclass:Dump")  = 2,   = "",   = ""  = 3,   = "",   = ""  = 5,   = "",   = "" >set r="result" do tmp.Do("test.myclass:Dump",.r,"p1","p2")  = 2,   = "result",   = "p1,p2"  = 3,   = "result",   = "p1,p2"  = 5,   = "result",   = "p1,p2"
      
      







数字付きの他の例


 >kill r do tmp.Do("test.myclass:Sum",.r) write r 10 >kill r do $system.OBJ.DisplayError(tmp.Do("test.myclass:Sum",.r,5))  #5001:    : 5 >do $system.OBJ.DisplayError(tmp.Do("PrintLn"))  #5654:  '2:PrintLn'   >do $system.OBJ.DisplayError(tmp.Do("test.myclass:PrintLn"))  #5001:  PrintLn     test.myclass >set r=10 do tmp.Do(,.r) write r 20 (=10 +2+3+5) >kill r do tmp.Do(,.r) write r 10 (=2+3+5) >set r=-10 do tmp.Do("+",.r) write r 0 (=-10 +2+3+5) >set r=1 do tmp.Do("*",.r) write r 30 (=2*3*5) >kill r do tmp.Do("_",.r,"^") write r ^2^3^5 (  ) >do tmp.Do("min",.r) write r 2 () >do tmp.Do("max",.r) write r 5 () >do tmp.Do("avg",.r) write r 3.333333333333333334 (=(2+3+5)/3) >kill r do tmp.Do($listbuild("set args(1,1)=args(1,1)+el"),.r) write r 10 (=2+3+5) >set r="r" do tmp.Do($listbuild("do sub^prog(el,args...)"),.r,"p1","p2") -------- el = 2 args=1 args(1)=3 args(1,1)="r" args(1,2)="p1" args(1,3)="p2" -------- el = 3 args=1 args(1)=3 args(1,1)="r" args(1,2)="p1" args(1,3)="p2" -------- el = 5 args=1 args(1)=3 args(1,1)="r" args(1,2)="p1" args(1,3)="p2" >set r="r" do tmp.Do($listbuild("do1 sub^prog(el,args...)"),.r,"p1","p2")  #5745:  !
      
      









オブジェクトのコレクションの使用例



初期化:

 set list=##class(%ListOfObjects).%New() for i="f1","f2","f3" do list.Insert(##class(test.myclass).%New(i)) set tmp=##class(test.ForEach).%New(list)
      
      







ターミナルをチェックインします。

 >do tmp.Do("test.myclass:Dump")  = "f1",   = "",   = ""  = "f2",   = "",   = ""  = "f3",   = "",   = "" >do tmp.Do("PrintLn") "f1" "f2" "f3" >do tmp.Do("PrintLn",," = ")  = "f1"  = "f2"  = "f3" >kill r do tmp.Do("Concat",.r,"**") write r **f1**f2**f3 >kill r do $system.OBJ.DisplayError(tmp.Do("Concat",.r,"f3"))  #5001:    : f3 >do $system.OBJ.DisplayError(tmp.Do("PrintLn1"))  #5654:  'test.myclass:PrintLn1'   >do $system.OBJ.DisplayError(tmp.Do("Sum",.r))  #5001:  Sum      test.myclass >do tmp.Do("SetField",,"blablabla"), tmp.Do("PrintLn",," = ")  = "blablabla"  = "blablabla"  = "blablabla" >do tmp.Do($listbuild("do el.PrintLn(.args)")) "blablabla" "blablabla" "blablabla" >do tmp.Do($listbuild("write ""field="",el.field,!")) field=blablabla field=blablabla field=blablabla
      
      







配列、グローバル、テーブル、ストリームなど、他のタイプのコレクションは無視されました。 しかし、今では「仕組み」を知っています...



クラスと例のソース。



免責事項この記事は、匿名のままにしたい著者の許可を得て公開されました。



ご清聴ありがとうございました!



All Articles