SYMPUT関数の使用

[OS]ALL
[リリース] 5.18, 6.07, 6.08, 6.09, 6.10
[キーワード] base, datastep, %put, run, statement, macro, variable, call, symput, doublequote

[質問]

以下のDATAステップでSYMPUTルーチンで作成したマクロ変数が、思ったように参照できません。なぜでしょうか。

data _null_;
  set sasuser.class;
  retain max 0;
  if max<weight then do;
    call symput('NUM',trim(put(height,best.)));
    %put &NUM;
  end;
run;


[回答]

DATAステップの実行は、次の3つのステップに分かれます。

  1. ステートメントの読み込みとマクロ(またはマクロ変数の展開)
  2. プログラムのコンパイル
  3. プログラムの実行

ステップ1からステップ2に移るタイミングは、RUNまたは別のPROCおよびDATAステートメントを読み込んだときです。
CALL SYMPUTルーチンはDATAステップの機能ですから、実行されるのは上記のステップ3になります。

一方、%PUTステートメントは、そのステートメントを読み込んだ時点で実行されます。 質問のプログラム例で%PUTステートメントが実行されるのは、RUNステートメントの読み込み前、すなわち上記のステップ1です。
したがって、%PUTステートメントで参照されるマクロ変数NUMは未定義になるか、古い値を参照してしまいます。

SYMPUTステートメントで設定した後の値をSASログに表示させるには、プログラムを次のように書き変えるのがもっとも簡単です。

data _null_;
  set sasuser.class;
  retain max 0;
  if max<weight then do;
    call symput('NUM',trim(put(height,best.)));
  end;
run;
%put &NUM;

つまり、RUNステートメントと%PUTステートメントを入れ変えるだけです。
%PUTステートメントの前にRUNステートメントを置くことにより、DATAステップの実行が 保証されます。そしてDATAステップの実行後に、%PUTステートメントが読み込まれて実行されることになります。