DATA Step, Macro, Functions and more

call execute with macro as an argument

Accepted Solution Solved
Reply
Regular Contributor
Posts: 234
Accepted Solution

call execute with macro as an argument

[ Edited ]

Hello,

 

In the following code, can we say macro %datasets is enclosed in single quotes or three parts  ie. '%datasets(name= ', strip(name), and  ');'  are concatenated by ||.  Which one is correct? 

 

data _null_;

     set sashelp.class;

     call execute('%datasets(name='||strip(name)||');');

run;

 

Below example is taken from Carpenter's macro book where author has mentioned "Because the %PRTDSN is enclosed in single quotes, the text is not seen as macro reference when data step is compiled".

 

data  _null_;

   set macro3.dbdir;

   call execute ('%prtdsn(dsn='||dsn||')');

run;

 

Thanks !

 


Accepted Solutions
Solution
‎09-25-2016 07:56 PM
Super User
Super User
Posts: 6,500

Re: call execute with macro as an argument

[ Edited ]

When SAS is parsing the code the character string %DATASETS does NOT trigger a macro call because it is enclosed in single quotes.  When the data step is running this code snippet 

'%datasets(name='||strip(name)||');'

will generate the charater strings like:

%datasets(name=Alfred);

Which will be passed to CALL EXECUTE. to be parsed. Since SAS can now see the %DATASETS it will run the macro and store the generated code into the execution stack to run AFTER the data step stops.  You can tell because the lines in the SAS log that begin with + that show the code that CALL EXECUTE generated you will see the actual code the macro generates but you will NOT see the macro call itself. This can cause timing issue, especially if the macro code generates and uses macro variables.

 

You can fix this by using the %NRSTR() macro quoting function in your original data step code like this:

'%nrstr(%datasets)(name='||strip(name)||');'

To see the difference try runing this simple example.

%macro datasets(name); %unquote(* NAME = &name ;) %mend datasets;
data _null_;
  set sashelp.class (obs=2);
  call execute('%datasets(name='||strip(name)||');');
  call execute('%nrstr(%datasets)(name='||strip(name)||');');
run;

 Results:

1    + * NAME = Alfred ;;
2    + %datasets(name=Alfred);
3    + * NAME = Alice ;;
4    + %datasets(name=Alice);

 

View solution in original post


All Replies
Super User
Posts: 17,831

Re: call execute with macro as an argument

If it's not in double quotes SAS sees it as a string. The code above generates a string that is passed to call execute. In this case that string ends up resolving to a macro call but it certainly doesn't have to. 

Regular Contributor
Posts: 234

Re: call execute with macro as an argument

@Reeza  For me, it is easier to understand as three strings concatenated by || as the argument of the call execute has to be string. But I might be misunderstanding it.

Super User
Posts: 17,831

Re: call execute with macro as an argument

That's correct, but String + string = String 

Smiley Very Happy

 

Super User
Posts: 5,083

Re: call execute with macro as an argument

You can use whatever wording you are comfortable with, but the process is this.  The DATA step puts together all the strings into a single string, before CALL EXECUTE sees it.  CALL EXECUTE sees just one string.  In a way, you can reason this out for yourself if you consider that CALL EXECUTE would not be expected to parse ||.

 

Also note, while Carpenter's book is correct, the execution phase of the DATA step does recognize the macro call (even if compilation does not).  CALL EXECUTE will execute macro language statements as soon as possible, without necessarily waiting for the current DATA step to finish.  It is a very tricky issue.

 

Respected Advisor
Posts: 4,649

Re: call execute with macro as an argument

Simplify your code by being more explicit :

 

data _null_;
    set sashelp.class;
    macroCall = cats('%datasets(name=', name, ');');
    put macroCall= ; /* for debug */
    call execute(macroCall);
run;

 

 

PG
Solution
‎09-25-2016 07:56 PM
Super User
Super User
Posts: 6,500

Re: call execute with macro as an argument

[ Edited ]

When SAS is parsing the code the character string %DATASETS does NOT trigger a macro call because it is enclosed in single quotes.  When the data step is running this code snippet 

'%datasets(name='||strip(name)||');'

will generate the charater strings like:

%datasets(name=Alfred);

Which will be passed to CALL EXECUTE. to be parsed. Since SAS can now see the %DATASETS it will run the macro and store the generated code into the execution stack to run AFTER the data step stops.  You can tell because the lines in the SAS log that begin with + that show the code that CALL EXECUTE generated you will see the actual code the macro generates but you will NOT see the macro call itself. This can cause timing issue, especially if the macro code generates and uses macro variables.

 

You can fix this by using the %NRSTR() macro quoting function in your original data step code like this:

'%nrstr(%datasets)(name='||strip(name)||');'

To see the difference try runing this simple example.

%macro datasets(name); %unquote(* NAME = &name ;) %mend datasets;
data _null_;
  set sashelp.class (obs=2);
  call execute('%datasets(name='||strip(name)||');');
  call execute('%nrstr(%datasets)(name='||strip(name)||');');
run;

 Results:

1    + * NAME = Alfred ;;
2    + %datasets(name=Alfred);
3    + * NAME = Alice ;;
4    + %datasets(name=Alice);

 

☑ This topic is SOLVED.

Need further help from the community? Please ask a new question.

Discussion stats
  • 6 replies
  • 398 views
  • 6 likes
  • 5 in conversation