quote array element inside macro do loop

蓝咒 提交于 2019-12-13 05:27:14

问题


I can call the macro VIO by %VIO(Dow=Fri,Hour=8) without error. Now I want to nest the call macro inside a do loop.

Here's what I have tried but no luck.

%macro trythis;
  data _null_;
    array ay[3] $3 ('Fri' 'Sat' 'Sun');
    %do i = 1 %to dim(ay);
      %do j = 1 %to 24;
         %VIO(ay[&i],&j);
      %end;
    %end;   
  run;
%mend;

%macro VIO(Dow,Hour);
  data Want&Dow.&Hour;
    set have(where=(hour="&Hour"));
    format dow $3.;
    dow = "&Dow";
  run;
%mend;

It seems ay[&i] will resolve to ay[1] not Fri.


回答1:


You can't exchange data with macro variables that way. Macro variables and macro calls resolve before the data step is even compiled, not to mention run. This is nice because it allows macro variables and macros to affect the data step compilation (ie, define which columns are present, for example). It also means you can't do what you're trying to do. Despite its similarities, the SAS Macro language is not a method of writing functions in SAS. You can write certain function-style macros, but that's not the same thing.

You don't specify what your macro does, so it's difficult to fully answer how to fix this.

If your macro takes a value and does things with it in the macro language, and you need to interact with the data step, you have several options:

  1. Rewrite your macro in FCMP (SAS's function-writing language)
  2. Rewrite your macro to use the data step in the macro rather than macro language elements where needed to be able to take the name of the array element rather than its value as an argument
  3. Use multiple data steps to accomplish your task
  4. Use RUN_MACRO and/or DOSUBL (possibly in combination with FCMP). This is very likely the slowest method, but it is also most similar to what you're trying to do. Dylan Ellis' RUN_MACRO Run! explains this method in detail.

If you don't need to interact with the data step, this may be easier to do.

Macro Arrays aren't quite the same as data step arrays. They're not an actual feature of the programming language; they're a hack. You can search for papers on them on the internet; for example, Tight Looping with Macro Arrays explains one example.

The general principle, though, is very straightforward. You use multiple ampersands to multiply resolve something.

%let ay1 = Fri;
%let ay2 = Sat;
%let ay3 = Sun;

%let i=2;

%put &&ay&i.;

This will resolve as you expect. The double ampersand tells SAS to delay resolution one pass, so &&ay&i becomes &ay1 when &i resolves but the double && just changes to a single & and ay is left alone.

So you can do something easy with the do loop:

%macro trythis;
  %let ay1=Fri;
  %let ay2=Sat;
  %let ay3=Sun;
  %do i = 1 %to 3;
    %do j = 1 %to 24;
        %VIO(&&ay&i.,&j);
    %end;
  %end;   
%mend;

Now, I want to state very clearly: the general approach you are taking here is very likely a poor one, both from an easy-to-program point of view and a speed point of view. You don't give visibility to %vio, so it's hard to say what you're doing or what the right approach is, but this is very likely not the right one. At minimum, splitting all of the parts up into three or four macros that clearly substantially interdepend will lead to complexity to maintain, and repeatedly running a datastep with a single where clause is very, very slow.



来源:https://stackoverflow.com/questions/29598841/quote-array-element-inside-macro-do-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!