★SASマクロに比べてDS2のメソッドが優れている点★の一つ、オーバーロード(多重定義)が可能なこと

良くも悪くもSASはプログラミング言語としてシンプルかつ、かなりトラディッショナル(上品な言い方にしてます)なとこがあります。
SASに慣れた人からするとSASマクロの仕組みにそれほど疑問は抱かないかもしれないですが、モダンな他言語をやっている人から見ると結構、えぇ~ってとこがあるみたいです。

そのひとつが今回紹介するオーバーロードという機能です。
簡単にいうと、引数の数が違ったり、型は違うんだけど、処理の内容は似ている機能を
同名で多重に定義してまとめることができるということです。
それによって呼び出された際に引数に応じて適切な処理が行われるので、呼び出し側で余計なこと考えなくていいし、似た名前の機能が乱立しない、条件分岐ではなく独立しているので管理しやすい等のメリットがあります

SASマクロは、同じ名前で定義するとフツーに上書きされてしまうので、マクロ処理の中に引数の数や型を判定する分岐を入れるか、別マクロを増やすしかないんですね。極端な例を見てみましょう。

ある部署では、2つの数をかけるという処理が多かったので、以下のようなマクロを作っていました

%macro v1(p1,p2);
 &p1 * &p2;
%mend v1;

次のように使っています。

data a;
x=%v1(3,2)
run;

ところが、ある時に3つの数をかける処理もでてきました。

ここで選択肢は2つあります。

①今まで使っていた%v1の内容を以下のように変える

%macro v1(p1,p2,p3);
%if &p3 ne %str() %then &p1 * &p2 * &p3;
%else &p1 * &p2;
%mend v1;

上記でOKですが、他のメンバーから、色んなところで使っている%v1マクロの中身を変えたら、今まで正常に動いていた箇所もチェックする必要があって怖いという意見がでます。

じゃあ、②新しいマクロを増やす

%macro v2(p1,p2,p3);
 &p1 * &p2 * &p3;
%mend v2;

を作って引数3の時はv2を使おうとなりました。

ところがしばらくすると、引数4の場合もでてきました。
さらに引数が文字のケースも増えてきました。さらに.....
といった度に、分岐を増やすか、マクロを新規にたてるかとやっているうちに、パラメーターの化け物かっていうマクロが生まれたり、共有マクロライブラリの中身が似たような名前のマクロでカオスにっていうのはよくある話ですよね。


これをDS2で考えて見ましょう。マクロカタログはパッケージに、マクロはメソッドになるとイメージしてください。

data Q1;
a=2;
b=3;
c=4;
d='1';
e='9';
run;

というテストデータがあります。

そして以下のコードでpackという名前のパッケージの中に、vという名前のメソッドを3ついれています。これが今までの%macro ~%mendで定義していたような箇所にあたると考えておいてください。
今はパッケージをworkにつくっているので、SASを閉じれば消えます。消したくなければ永久ライブリに作ってください。

proc ds2 libs=work;
package pack/overwrite=yes;

method v(double p1, double p2) returns double;
return p1 * p2 ;
end;

method v(double p1,  double p2,  double p3) returns double;
return p1 * p2 * p3 ;
end;

method v(char p1,  char p2) returns double;
return inputn(p1,'best.') * inputn(p2,'best.');
end;

endpackage;
run;
quit;

で注目は同じ名前でvを3つ作ってますがv( )の括弧内の部分、ここが引数の設定なのですが、そこがそれぞれ違います。
1つ目は引数が二つで、数値の場合
2つ目は引数が三つで、数値の場合
3つ目は引数が二つで、文字の場合
です

さて、では実際、定義したメソッドを呼び出して使ってみましょう

proc ds2 libs=work;
data A1/overwrite=yes;
declare double x1 x2 x3;
declare package pack p();
keep x1 x2 x3;
method run();
set Q1;
x1=p.v(a,b);
x2=p.v(a,b,c);
x3=p.v(d,e);
end;
enddata;
run;
quit;

結果は






となって、引数ばらばらなのに全部vメソッドで処理できました。ということです。

もし、エラーが起きたら、どの引数パターンの時に起きたかをたどれば、どのメソッドに問題があるかわかるのでデバックも楽ですし、同名で追加するだけなので、今までの正常に動いているメソッドに触る必要もありません。

どうです?そろそろDS2、気になってきませんか?

0 件のコメント:

コメントを投稿