I got this from Carpenter's book (Complete Guide to the SAS Macro language):
%macro abc;
*%put #1#@ In abc;
%mend;
%macro doit;
*%abc
%put #2#@ Here;
*%let x=%abc;
%put #2#@ &=x;
%mend;
%doit;
I assumed * will not work inside of a macro, but got results as here:
#2#@ Here
#1#@ In abc
#2#@ X=*
This indicates that the * does comment out %abc. Why?
Looks like it worked to me. Make sure to turn on MPRINT so you can see the statement comments that you are generating.
1 %macro abc; 2 *%put #1#@ In abc; 3 %mend; 4 5 6 7 %macro doit; 8 *%abc 9 %put #2#@ Here; 10 *%let x=%abc; 11 %put #2#@ &=x; 12 %mend; 13 14 15 options mprint; 16 %doit; #2#@ Here MPRINT(DOIT): *%abc #1#@ In abc #2#@ X=* MPRINT(): * 17 ;;;;
But it really does not make much sense to put in a statement comment that does not actually include any comment text. And even worse to put in one that does not have an ending semicolon.
Let's examine your ABC macro. The first and last lines just define the start and end of the macro definition. The middle line starts a comment. Then it has a complete macro statement (%put statement.) but it never ends the comment.
So when you call that macro whatever text you have following the macro up to the next semicolon will become the text of the comment.
So this example usage of %ABC
18 %macro doit(); 19 data _null_; 20 %abc 21 set sashelp.class; 22 run; 23 %mend; 24 25 options mprint; 26 %doit() MPRINT(DOIT): data _null_; #1#@ In abc MPRINT(ABC): * MPRINT(DOIT): set sashelp.class; MPRINT(DOIT): run; NOTE: DATA statement used (Total process time): real time 0.02 seconds cpu time 0.03 seconds
caused the %DOIT macro to generate three statements. A DATA and a RUN statement with a comment statement in the middle.
That missing semicolon is that is causing the MPRINT lines to look so strange in your original example. If we include the semicolon into the definition of ABC then it looks better.
If you want your macro to emit statement comments you should take care to include the ending semicolon in the macro definition.
For example like this:
%macro print(data);
* This macro prints a dataset ;
proc print data=&data;
run;
* This is the last statement generated by the macro ;
%mend print;
So if you run that macro (with MPRINT on) you get this in the SAS log.
48 %print(sashelp.class) MPRINT(PRINT): * This macro prints a dataset ; NOTE: Writing HTML Body file: sashtml.htm MPRINT(PRINT): proc print data=sashelp.class; MPRINT(PRINT): run; NOTE: There were 19 observations read from the data set SASHELP.CLASS. NOTE: PROCEDURE PRINT used (Total process time): real time 1.55 seconds cpu time 1.03 seconds MPRINT(PRINT): * This is the last statement generated by the macro ;
If you want to comment out macro code then either using BLOCK comments /* ... */.
Or use a MACRO comment %* .... ;
The documentation is clear.
In your sample code the %put statement from macro %abc gets written to the log so macro %abc gets executed as well as the %put statement within the macro
In your code the comment doesn't get ended with a semicolon on the same line.
But still the macro executes. The timing is a bit weird like why does this %put statement then only write to the 2nd line in the code - but given you use a comment syntax that's not supported for the macro language unexpected results are always possible.
I think you should use “%*” , not "*%" 。
Both "%*" and "/* */" could comment out the code in MACRO , not "*%" .
Looks like it worked to me. Make sure to turn on MPRINT so you can see the statement comments that you are generating.
1 %macro abc; 2 *%put #1#@ In abc; 3 %mend; 4 5 6 7 %macro doit; 8 *%abc 9 %put #2#@ Here; 10 *%let x=%abc; 11 %put #2#@ &=x; 12 %mend; 13 14 15 options mprint; 16 %doit; #2#@ Here MPRINT(DOIT): *%abc #1#@ In abc #2#@ X=* MPRINT(): * 17 ;;;;
But it really does not make much sense to put in a statement comment that does not actually include any comment text. And even worse to put in one that does not have an ending semicolon.
Let's examine your ABC macro. The first and last lines just define the start and end of the macro definition. The middle line starts a comment. Then it has a complete macro statement (%put statement.) but it never ends the comment.
So when you call that macro whatever text you have following the macro up to the next semicolon will become the text of the comment.
So this example usage of %ABC
18 %macro doit(); 19 data _null_; 20 %abc 21 set sashelp.class; 22 run; 23 %mend; 24 25 options mprint; 26 %doit() MPRINT(DOIT): data _null_; #1#@ In abc MPRINT(ABC): * MPRINT(DOIT): set sashelp.class; MPRINT(DOIT): run; NOTE: DATA statement used (Total process time): real time 0.02 seconds cpu time 0.03 seconds
caused the %DOIT macro to generate three statements. A DATA and a RUN statement with a comment statement in the middle.
That missing semicolon is that is causing the MPRINT lines to look so strange in your original example. If we include the semicolon into the definition of ABC then it looks better.
If you want your macro to emit statement comments you should take care to include the ending semicolon in the macro definition.
For example like this:
%macro print(data);
* This macro prints a dataset ;
proc print data=&data;
run;
* This is the last statement generated by the macro ;
%mend print;
So if you run that macro (with MPRINT on) you get this in the SAS log.
48 %print(sashelp.class) MPRINT(PRINT): * This macro prints a dataset ; NOTE: Writing HTML Body file: sashtml.htm MPRINT(PRINT): proc print data=sashelp.class; MPRINT(PRINT): run; NOTE: There were 19 observations read from the data set SASHELP.CLASS. NOTE: PROCEDURE PRINT used (Total process time): real time 1.55 seconds cpu time 1.03 seconds MPRINT(PRINT): * This is the last statement generated by the macro ;
If you want to comment out macro code then either using BLOCK comments /* ... */.
Or use a MACRO comment %* .... ;
Thanks for the help. I am trying to understand why * before %abc does block the execution of the macro, whereas it does not in
*%let x=%abc;
I am not sure if ";" plays any role after *%abc since it does not change the result at all.
@jason4sas wrote:
Thanks for the help. I am trying to understand why * before %abc does block the execution of the macro, whereas it does not in
*%let x=%abc;I am not sure if ";" plays any role after *%abc since it does not change the result at all.
Are you sure it did not work? It is very hard to tell when the only SAS code the macro logic is generating are * characters and semicolons. And it is doubly confusing when the macro calls do NOT supply the closing semicolon for the last SAS statement they generate. The effect is that when the statement does finally get finished it ends up running after the macro has finished. Again it is very hard to see these effect completely when the only SAS code the macro logic is generating are comment statements, since by definition a comment statement does not have any real effect.
That line you showed is trying to start a statement comment. Then it runs a macro statement, %LET. Since the call to %ABC is going to generate another * you should get an * into the macro variable X.
Thanks Tom's mprint, I might have got the reason: *%abc does not contain macro statements, so it was put in the word queue where the statement is regarded as SAS statement and * does work then to comment out %abc. However, %let is a standard macro statement so it got executed immediately. Please straighten me out if it still is not much correct.
I think you have it.
You can seem something similar with just macro variable resolution.
1 %macro test(parm1); 2 %put NOTE: &sysmacroname: &=parm1 ; 3 * The value of PARM1 is &parm1 ; 4 %put The value of PARM1 is &parm1 ; 5 %mend test; 6 7 %test(xxx) MLOGIC(TEST): Beginning execution. MLOGIC(TEST): Parameter PARM1 has value xxx MLOGIC(TEST): %PUT NOTE: &sysmacroname: &=parm1 NOTE: TEST: PARM1=xxx MPRINT(TEST): * The value of PARM1 is &parm1 ; MLOGIC(TEST): %PUT The value of PARM1 is &parm1 The value of PARM1 is xxx MLOGIC(TEST): Ending execution.
I'm also surprised that a * comment in a macro definition can comment out a macro invocation:
options mlogic ;
%macro abc();
%put I do not execute ;
%mend;
%macro doit() ;
* %abc() ;
%mend;
%doit()
I think you're right that officially a macro invocation is not a macro language statement. So perhaps this behavior is undefined by the documentation.
But I don't think the macro call should go to the word queue. I would expect when the above macro executes the * would go to the word queue, the macro call %abc would execute, and then the semicolon would go to the word queue. But obviously that's not what happens.
My guess is it has something to do with the macro language compiler. Clearly when the macro is compiled, the compiler is looking inside of * comments. This is because the * has no meaning to the macro compiler. And it is why macro statements inside of a * comment will be compiled (and later executed). I suppose it's possible that a macro invocation is not compiled in the same way as a macro statement is compiled.
Okay, here's another oddity. With this code:
options mlogic ;
%macro abc();
Hello world
%mend;
%macro doit() ;
* %abc() ;
%mend;
If I code:
%doit()
the macro ABC is not invoked. But if I code:
%put %doit() ;
the macro ABC is invoked.
So I'm not sure what to conclude, except that the * is not a comment in the macro language, and when you use * comments inside a macro definition, behavior can be odd.
I'm away from my bookcase. Does Art not explain this behavior?
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.