前のページ|次のページ

CALL SYMPUTルーチンを使用したスコープの特殊なケース

CALL SYMPUTルーチンの概要

CALL SYMPUTに伴うほとんどの問題は、マクロ変数を作成するCALL SYMPUTステートメントと、その変数を使用するマクロ変数参照との間に、正確なステップ境界が不足していることに関係しています。(詳細については、CALL SYMPUTルーチンを参照してください)。ただし、CALL SYMPUTが作成するマクロ変数のスコープに関連して、特殊なケースがいくつか存在します。これらのケースは、なぜ変数へのスコープの割り当てをSASに任せず、常に自分で変数にスコープを割り当ててから値を割り当てる必要があるのかについての良い例になります。
次の2つのルールは、CALL SYMPUTが変数を作成する場所を制御します。
  1. CALL SYMPUTは、DATAステップの実行中に、現在使用可能なシンボルテーブルが空ではないという条件で、そのシンボルテーブルにマクロ変数を作成します。そのテーブルが空の(ローカルマクロ変数を含まない)場合、通常、CALL SYMPUTは最も近い空でないシンボルテーブルに変数を作成します。
  2. ただし、ローカルシンボルテーブルが空であっても、CALL SYMPUTによってそのシンボルテーブルに変数が作成される、次の3つのケースがあります。
    • SASバージョン8以降、PROC SQLの後でCALL SYMPUTを使用すると、ローカルシンボルテーブルに変数が作成されます。
    • マクロの呼び出し時にマクロ変数SYSPBUFFを作成すると、ローカルシンボルテーブルに変数が作成されます。
    • 実行中のマクロに計算される%GOTOステートメントが含まれる場合、ローカルシンボルテーブルに変数が作成されます。計算される%GOTOステートメントは、&または%が含まれるラベルを使用する%GOTOステートメントです。つまり、計算される%GOTOステートメントには、テキスト式を生成するマクロ変数参照またはマクロ呼び出しが含まれます。計算される%GOTOステートメントの例を次に示します。
      %goto &home;
現在DATAステップで使用可能なシンボルテーブルは、DATAステップが完了したとSASが判断したときに存在するシンボルテーブルです。(SASは、RUNステートメント、データ行の後のセミコロン、または別のステップの開始を検出すると、DATAステップが完了したと見なします。)
実行中のマクロに計算される%GOTOステートメントが含まれる場合、またはマクロの呼び出し時にマクロ変数SYSPBUFFを作成した場合、ローカルシンボルテーブルが空であっても、空でない場合と同様にCALL SYMPUTが動作してローカルマクロ変数が作成されます。
CALL SYMPUTルーチンがどのシンボルテーブルに変数を作成したかを調べるために、_USER_オプションを指定して%PUTステートメントを使用すると役立つことがあります。

完全なDATAステップと空でないローカルシンボルテーブルを用いたCALL SYMPUTの使用例

次の例について検討します。この例では、マクロ内に、CALL SYMPUTステートメントを含む完全なDATAステップが含まれています。
%macro env1(param1);
   data _null_;
      x = 'a token';
      call symput('myvar1',x);
   run;
%mend env1;

%env1(10)

data temp;
   y = "&myvar1";
run;
これらのステートメントをサブミットすると、次のエラーメッセージが表示されます。
WARNING:   Apparent symbolic reference MYVAR1 not resolved.
このメッセージが表示されるのは、次にあげる理由からです。
  • DATAステップがENV1の環境内で完了している(つまり、RUNステートメントがマクロに含まれている)
  • ローカルシンボルテーブルが空でない(パラメータPARAM1が含まれる)
したがって、CALL SYMPUTルーチンによってENV1のローカル変数としてMYVAR1が作成されます。この変数は、グローバルマクロ変数を期待するその後のDATAステップでは使用できません。
スコープを表示するには、_USER_オプション付きの%PUTステートメントをマクロに追加し、同様のステートメントをオープンコードにも追加します。ここで、前と同様に次のマクロを呼び出します。
%macro env1(param1);
   data _null_;
      x = 'a token';
      call symput('myvar1',x);
   run;

   %put ** Inside the macro: **;
   %put _user_;
%mend env1;

%env1(10)

%put ** In open code: **;
%put _user_;

data temp;
   y = "&myvar1";  /* ERROR - MYVAR1 is not available in open code. */
run;
これらの%PUT _USER_ステートメントを実行すると、次の情報がSASログに書き込まれます。
**Inside the macro:** ENV1 MYVAR1 a token ENV1 PARAM1 10 ** In open code:**
CALL SYMPUTによって、ENV1のローカルシンボルテーブルに、マクロ変数MYVAR1が作成されます。グローバルマクロ変数が作成されないため、オープンコード内の%PUT _USER_ステートメントは、SASログに何も書き込みません。
次の図に、この例のすべてのシンボルテーブルを示します。
完全なDATAステップを生成するCALL SYMPUTルーチンを使用したシンボルテーブル
完全なDATAステップを生成するマクロ内のCALL SYMPUTルーチン

不完全なDATAステップを用いたCALL SYMPUTの使用例

次に示すマクロENV2に含まれるDATAステップは、RUNステートメントがないため不完全です。
%macro env2(param2);
   data _null_;
      x = 'a token';
      call symput('myvar2',x);
%mend env2;

%env2(20)
run;

data temp;
   y="&myvar2";
run;
これらのステートメントは、エラーを出力せずに実行されます。DATAステップは、SASが(この場合はオープンコード内の)RUNステートメントを検出して、初めて完全になります。したがって、DATAステップの現在のスコープは、グローバルスコープです。CALL SYMPUTによってグローバルマクロ変数としてMYVAR2が作成され、その後のDATAステップでこの値を使用できます。
ここでも、スコープを表示するために、次のように_USER_オプション付きで%PUTステートメントを使用します。
%macro env2(param2);
   data _null_;
      x = 'a token';
      call symput('myvar2',x);

   %put ** Inside the macro: **;
   %put _user_;
%mend env2;

%env2(20)

run;

%put ** In open code: **;
%put _user_;

data temp;
   y="&myvar2";
run;
ENV2内の%PUT _USER_ステートメントが実行されると、次のメッセージがSASログに書き込まれます。
**Inside the macro:** ENV2 PARAM2 20
オープンコード内の%PUT _USER_ステートメントによって、次のメッセージがSASログに書き込まれます。
**In open code:** GLOBAL MYVAR2 a token
次の図に、この例に含まれるすべてのスコープを示します。
不完全なDATAステップを生成するCALL SYMPUTルーチンを使用したシンボルテーブル
不完全なDATAステップを生成するマクロ内のCALL SYMPUTルーチン

完全なDATAステップと空のローカルシンボルテーブルを用いたCALL SYMPUTの使用例

次の例のENV3は、マクロパラメータを使用していません。そのため、ローカルシンボルテーブルは空です。
%macro env3;
   data _null_;
      x = 'a token';
      call symput('myvar3',x);
   run;

   %put ** Inside the macro: **;
   %put _user_;
%mend env3;

%env3

%put ** In open code: **;
%put _user_;

data temp;
   y="&myvar3";
run;
この場合、DATAステップは完全であるためマクロ内で実行されますが、ローカルシンボルテーブルは空です。そのため、CALL SYMPUTは、最も近く空でない使用可能なシンボルテーブル、つまりグローバルシンボルテーブルにMYVAR3を作成します。どちらの%PUTステートメントも、次のように、MYVAR3がグローバルシンボルテーブルに存在することを表示しています。
** Inside the macro: **
GLOBAL    MYVAR3   a token

** In open code: **
GLOBAL    MYVAR3   a token

SYSPBUFFと空のローカルシンボルテーブルを用いたCALL SYMPUTの使用例

次の例では、自動マクロ変数SYSPBUFFの存在によって、パラメータとローカルマクロ変数が両方ともマクロENV4に存在しない場合でも、ローカルシンボルテーブルが空でない場合と同様にCALL SYMPUTが動作します。
%macro env4 /parmbuff;
 data _null_;
      x = 'a token';
      call symput('myvar4',x);
   run;

   %put ** Inside the macro: **;
   %put _user_;
   %put &syspbuff;
%mend env4;

%env4

%put ** In open code: **;
%put _user_;
%put &syspbuff;

data temp;
   y="&myvar4";  /* ERROR - MYVAR4 is not available in open code */
run;
/PARMBUFFを指定することによって、自動マクロ変数SYSPBUFFが作成されます。そのため、マクロENV4を呼び出すとCALL SYMPUTによって、ENV4のローカルシンボルテーブルにマクロ変数MYVAR4が作成されます。これは、パラメータとローカルマクロ変数が両方ともマクロENV4に存在しない場合でも同様です。
%PUTステートメントの結果により、次が証明されます。
  • MYVAR4のスコープがENV4として示されている
  • SYSPBUFFがENV4に対してローカルであるため、オープンコードの%PUTステートメントでのSYSPBUFFへの参照は置換されていない
** Inside the macro: **
b ENV4     MYVAR4    a token

** In open code: **
WARNING: Apparent symbolic reference SYSPBUFF not resolved.
詳細については、SYSPBUFF自動マクロ変数を参照してください。
前のページ|次のページ|ページの先頭へ