Because the data step language and macro language are two different programming environments. When SAS tokenizes your statements, it looks for specific keywords. One of those keywords is the %
trigger. Before anything is run, the word scanner separates out macro statements from SAS statements and passes them to the appropriate processor. Macro statements are always compiled and resolved before SAS statements.
When you are working with macros, you're storing text strings in either some macro variable or macro program. Anything inside of the macro variable or program is raw text as far as SAS is concerned.
Consider the following two macros:
Macro 1:
%macro foo1;
data bar1;
var1 = 'a';
var2 = 'b';
var3 = 'c';
var4 = 'd';
keep var1-var3;
run;
%mend;
Macro 2:
%macro foo2;
keep
%do i = 1 %to 3;
var&i
%end;
%mend;
data bar2;
var1 = 'a';
var2 = 'b';
var3 = 'c';
var4 = 'd';
%foo2;
run;
When you compile Macro 1, nothing happens until you call it. This is because you have stored all of that text inside of a macro program. When you call the macro statement:
%foo1;
SAS passes the phrase foo1
to the macro processor, the program is run, and the resolved text is spat back into the word scanner, which then processes the individual tokens one by one. As far as SAS is concerned, it sees exactly the datastep contained inside:
data bar1;
var1 = 'a';
var2 = 'b';
var3 = 'c';
var4 = 'd';
keep var1-var3;
run;
When we run Macro 2, we'll get the exact same output, but it's being performed differently.
When we compile the macro foo2
, we also store some information about an internal macro loop. This particular loop simply creates the text "var1 var2 var3" sequentially. Notice that there's a piece of text right before the loop: "keep." This is completely valid since it's just a piece of text.
We execute the macro inside of the data step. When we start the compilation process of the data step, the word scanner finds the macro trigger %
and passes that information along to the macro processor. When it finds that foo2
is a valid compiled macro, the macro processor runs the macro program, and the resulting text is sent over to the word scanner:
keep
var1
var2
var3
We end invocation of the macro with a semicolon on purpose. This tells the word scanner that we are at the end of a statement, which eventually gets sent over to the compiler.
Once the macro is complete, the word scanner keeps chugging along, passing statements to the input stack until it hits the run
boundary, or another proc
step.
We could invoke foo2
outside of a data step, but SAS will error out saying that they're not valid statements. It's equivalent to typing keep var1 var2 var3;
on a line and trying to run it. That specific piece of text is only useful inside of a data step, though SAS will happily attempt to run it wherever you want.
SAS doesn't see macros. It only understands data step and proc language. Only the macro processor can see and make use of macro triggers. The word scanner prevents the compiler from seeing any of the macro triggers. Think of the word scanner like a special filter: it hands out text only to the places that can read it.
There are a few exceptions where some functions in the data step can bridge the gap between SAS and macros, but it doesn't really have anything to do with this.