SAS: Calling one macro from another…Order of Macro Definitions

In my code I have several macros. Macro A is the main macro. Macro A then calls macro B which in turn calls macro C.

In SAS, do I have to define them in backwards order? In other words, do I have to define macro C first, then macro B, then macro A last? Or does it matter since SAS reads all the code in before it actually hits the command to run the macros? For that matter, can I issue the command to run the macro as the first statement in my code and then define the macros below the command?

Thanks!

Answers


First, you must define a macro before it is called.

Second, it doesn't matter where the macro is invoked as long as you have loaded it before-hand.

To elaborate on your issue: The autocall library is your friend. If you SAS administrator won't allow you to put your macros in the autocall library, you can append the autocall like so:

filename mymacros 'c:\mysas'; 
/*this defines the directory you have stored your macros*/

options sasautos=(sasautos mymacros) mautosource;

a macro has to be defined before it is called. for performance reasons, it is best not to define a macro inside another -- if you do so, then it will be re-defined every time you call the outer macro. the following works fine:

%macro a;
  %put a;
  %b
%mend a;

%macro b;
  %put b;
  %c
%mend b;

%macro c;
  %put c;
%mend c;

%*-- %a is main --*;
%a
/* on log
a
b
c
*/

You must define a macro before it is called, so the line with "%A" would need to follow the definition of macro A. The order of the other macro definitions does not matter, as long as they are defined before they are called. Typically in my programs I set up a main macro like you describe, then the last line of the program calls this macro.

Another option to consider is to set up a macro autocall library, which contains the definitions of many macros. This works best for reusable macros, so that you do not have to redefine them in each program.


There are two aspects of macro code in SAS to be defined: the macro code that gets compiled and the macro parameters:

Macro code:

The macro code itself is very simple in that when the %macro token is encountered the SAS system starts to compile a SAS macro and keeps compiling until it hits a %mend token. The only real problems you can come up against is if you updated macro code and don’t recompile it before executing it – in these situations it will still run the old version it has in the macro library. By extension, if you try to compile a macro that calls another macro which hasn’t already been defined then you will get an error. For these reasons, they need to be programmed in the order in which they are called (as shown in below example: %level3 comes before %level2, which comes before %level1)

Macro variables: When defining macro variables there are two scopes: Global and Local. Once defined, global variables can be accessed anywhere and at any time. However, local variables only exist locally during the execution of the macro in which it has been defined. By extension, if the macro where the local variable has been defined calls any other macros, the local macro variable will still be accessible:

Working Example:

In the following example, the macros are defined in reverse order to prevent SAS returning an Apparent invocation of macro warning.

The below diagram illustrates the structure of the following macros in the following example:

|-----------------------------|
|GLOBAL                       |
|  |------------------------| |
|  |LEVEL1                  | |
|  |  |-------------------| | |
|  |  |LEVEL2             | | |
|  |  |  |--------------| | | |
|  |  |  |  LEVEL3      | | | |
|  |  |  |--------------| | | |
|  |  |-------------------| | |
|  |------------------------| |
|-----------------------------|

Compile the nested macros:

 %macro level3 ;
  %put **** START LEVEL3 **** ;
  %local G1;
  %let G1=Local ;

  %do i=1 %to 2 ;
    %put In the macro do loop I=&i ;
  %end ;

  %put The value of I at level3 is: &I ;
  %put Are we accessing global or local G1 variable here: &G1 ;

  %put **** END LEVEL3 ****;
%mend level3 ;


 %macro level2 ;
  %put **** START LEVEL2 **** ;
  %*global L1 ; *<-- this would produce an error because the variable name has already been added to the local scope in %level1 ;

  %put Are we accessing global or local G1 variable here: &G1 ;
  %put Can we access local variables here: &L1 ;

  %level3 ;

  %put The value of I in level2 is: &I ;
  %put **** END LEVEL2 ****;
%mend level2 ;

Compile the top level macro (which in turn calls the above two macros) and run it:

%let G1=Global;
%macro level1 ;
  %put **** START LEVEL1 **** ;
  %let L1=Yes;

  %put Are we accessing global or local G1 variable here: &G1 ;
  %put Can we access local variables here: &L1 ;

  %level2 ;

  %put The value of I outside of the local macro is: &I ;
  %put Are we accessing global or local G1 variable here: &G1 ;

  %put **** END LEVEL1 ****;
%mend level1 ;
%level1 ;

Points to note when reviewing the log:

  • Outside of %level3, &I returns a warning that the macro variable does not exist
  • Within %level3, when &G1 is called, it returns the value stored in the local scope of %level3.Once outside of %level3, the value returns to the value stored globally

Need Your Help

How does Elm compare to ClojureScript?

clojurescript elm

I'm reaching a point where GUI coding with Backbone.js object-oriented MVC pattern is getting quite complex, and looking around at other paradigms. MDV, FRP, ECS, oh my.

Groovy sql errors on remote Mysql server?

sql grails groovy

I'm using groovy gsql to query to Mysql database.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.