マクロ変数のスコープに関連する問題を解決しようとしているときに、この非常に役立つ SO ページを見つけました。 %let がローカル マクロ変数を作成しないのはなぜですか?
要約すると、%let x = [];
または%do x = [] %to [];
マクロで記述すると、次のようになります。
- グローバル シンボル テーブルに「x」が存在しない場合は、ローカル スコープのマクロ変数 x を作成します。または、
- 「x」がグローバルシンボルテーブルにある場合、グローバルスコープマクロ変数「x」を更新します
これは非常に非直感的だと思います。この設計の選択により、SAS の荒野に大量のバグが発生していることは間違いありません。「i」や「counter」などの一般的な変数名を使用するループ ステートメントの上であっても、マクロで %local ステートメントを目にすることはめったにありません。たとえば、SUGI および SAS グローバル フォーラムの論文のリストから、タイトルに「マクロ」という単語が含まれる最初の論文を見つけました 。 =スギ
実際、私が開いた最初の SAS カンファレンス ペーパーでこのコードを見つけました。
%macro flag;
data CLAIMS;
set CLAIMS;
%do j= 1 %to 3;
if icd9px&j in (&codelist)
then _prostate=1;
%end;
run;
%mend;
%flag;
http://support.sas.com/resources/papers/proceedings15/1340-2015.pdf
%flag を呼び出し、独自の &j 変数を持っている人は悲惨です。%flag を呼び出した後、どこでも &j が 4 になるため、ログ エラーは発生せず、偽の結果が簡単に発生する可能性があります。これは (経験上) 追跡するのが楽しくないバグになります。さらに悪いことに、彼らは自分の結果が偽物であることを決して認識しないかもしれません.
だから私の質問は、すべてのマクロ変数をデフォルトでローカルスコープにしないという決定がなされたのはなぜですか? SASマクロ変数のスコープがそのように機能するのには、正当な理由がありますか?