BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
jason4sas
Obsidian | Level 7

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?

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

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 %* .... ;

 

 

 

View solution in original post

8 REPLIES 8
Patrick
Opal | Level 21

The documentation is clear.

Patrick_1-1706487278523.png

 

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

Patrick_2-1706487355355.png

 

In your code the comment doesn't get ended with a semicolon on the same line.

Patrick_3-1706487460265.png

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. 

 

 

 

 

 

 

Ksharp
Super User

I think you should use “%*” , not "*%" 。

Both "%*" and "/* */" could comment out the code in MACRO , not "*%" .

Ksharp_0-1706493806784.png

 

Tom
Super User Tom
Super User

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 %* .... ;

 

 

 

jason4sas
Obsidian | Level 7

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.

Tom
Super User Tom
Super User

@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.

jason4sas
Obsidian | Level 7

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.

Tom
Super User Tom
Super User

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.
Quentin
Super User

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?

The Boston Area SAS Users Group is hosting free webinars!
Next webinar will be in January 2025. Until then, check out our archives: https://www.basug.org/videos. And be sure to subscribe to our our email list.

SAS Innovate 2025: Register Now

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!

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 8 replies
  • 1327 views
  • 3 likes
  • 5 in conversation