简体   繁体   中英

nesting a macro call within a macro in SAS

%outputter is a macro that generates a simulated result based on a set of arguments. The contents of this macro are elaborate and get in the way of the question, but note that the macro includes multiple DATA step and PROCs, and takes some numeric arguments to get it going. For example:

%outputter(arg_a=4, arg_b=2, arg_c=0.01)

I need to run the macro hundreds of times, iterating arg_c by 0.01 each time. I typically iterate with a macro wrapping around a PROC or DATA step. For example:

%macro iterater(first=0.01, last=1.50);
%do i=&first. %to &last. %by 0.01;

/*<insert relevant code here>*/

%end;
%mend iterater;

%iterater

But in this situation, the content of /*<insert relevant code here>*/ is the macro %outputter . In other words:

%macro iterater(first=0.01, last=1.50);
%do i=&first. %to &last. %by 0.01;

%outputter(arg_a=4, arg_b=2, arg_c=&i)

%end;
%mend iterater;

%iterater

This breaks, as you'd expect. I'm sure there's a way around this that involves modifying my %outputter macro, but I'd like to figure out how to nest the macro %outputter within the macro %iterator so that %outputter runs 150 times, each time with a different value for the arg_c argument that is specified by i from %iterator .

This question seems different from the other posts I have read through because my %outputter macro has (and needs for user functionality purposes) user-defined arguments.

Your code will actually work fine, if the DO loop is set properly - I think macro BY intervals requires whole numbers. There may be a workaround for that, but not that jumps to mind. Someone else can post that version of a solution.

%macro iterater(first=1, last=150);
%do i=&first. %to &last. ;

%let param = %sysevalf(&i/100);
%outputter(arg_a=4, arg_b=2, arg_c=&param)

%put &param.;

%end;
%mend iterater;

%iterater

Personally, I find debugging macro loops a massive pain, so I highly recommend CALL EXECUTE or DOSUBL instead. I prefer to generate the string separately as then I can pipe the data to a data set to confirm things are created correctly.

data demo_call;
 do i=0.01 to 1.5 by 0.01;
   str = catt('%nrstr(%outputter(arg_a=4, arg_b = 2, arg_c=',
               put(i, 8.2),
              '));');
   *once this is working, uncomment these lines to execute macro;
   *output;
   *call execute(str);
 end;
run;

EDIT1: fixed quoting issue with code (single/double mismatch). EDIT2: added %NRSTR to avoid run time issues. I don't know that it's needed here but better safe than sorry.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM