2014年7月19日土曜日

値をマクロ変数に格納する「CALL SYMPUTX」その2




前回の続きです。ちょっとした落とし穴を紹介。


まず以下の例を見てみましょう。

* マクロ変数を削除 ;
%symdel X  / nowarn;

* call symputxでマクロ変数を作りログに出力 ;
%macro TEST;
     data _null_;
         call symputx("X", "abcd");
     run;
%mend;
%TEST;

%put "&X";

ログ
"abcd"



ログを見てみると、問題なくマクロ変数を参照できてますね。
では次のプログラムはどうでしょうか?

* マクロ変数を削除 ;
%symdel X2 X3 / nowarn;

* call symputxでマクロ変数を作りログに出力 ;
%macro TEST2;
     %let X2=1;
     data _null_;
         call symputx("X3", "abcd");
     run;
%mend;
%TEST2;

%put "&X3";

ログ
WARNING: 記号参照X3を展開していません。


WARNINGが出て参照できませんでした。
最初のマクロとの違いと言えば「%let X2=1;」が追加されたくらいですが、実はこれが影響してます。


超ざっくり説明すると、「%let X2=1;」はマクロTEST2の中で定義してるマクロ変数で、いわゆるローカルマクロ変数(以下参照)です。

  ローカルマクロ変数:
   そのマクロ内でしか参照できないマクロ変数(マクロが実行終了すると消去される)

  グローバルマクロ変数:
   どの場所からでも参照できるマクロ変数


マクロの中でひとつでもローカルマクロ変数があると、同マクロ内に書かれたCALL SYMPUTXの結果もローカルマクロ変数となります。(グローバルマクロ変数になる場合もある。詳細はこちらを参照)





もしグローバルマクロ変数に変えたい場合、はじめに「%GLOBAL マクロ変数名;」を追記すればOK。
逆にローカルマクロ変数にしたい場合は、%LOCALステートメントを追記します。

またSYMPUTにはなくSYMPUTXのみの機能として以下のように書けちゃいます。

  call symputx("X3", "abcd" , "G") ;

  "G" …  グローバルマクロ変数にする。
  "L"  …  ローカルマクロ変数にする(マクロ外で実行するとグローバルマクロ変数になる)


この点もCALL SYMPUTXを使うメリットだと思います。


2 件のコメント:

  1. 釈然としなかった問題でした。素晴らしい!

    返信削除
  2. ありがとうございます!
    コメント頂けると励みになります。


    返信削除