Date: Mon, 25 Nov 2002 11:13:05 -0500
Reply-To: Ian Whitlock <WHITLOI1@WESTAT.COM>
Sender: "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From: Ian Whitlock <WHITLOI1@WESTAT.COM>
Subject: Re: macro resolution inside *-comments
Content-Type: text/plain; charset="iso-8859-1"
Quentin,
You have opened an old can of worms. Let's look at the logical problems.
Fact 1: The SAS code
* something ;
is a SAS comment. In particular, it is SAS code, in contrast to
/* something */
which is simply a comment.
Fact 2: SAS macro is a system of instructions for generating SAS code.
Question: Can a generated system of code make comments on the generating
system?
Now we have a conflict of interest - who owns what comments? Well, in the
beginning:
/* something */
was a comment through out the system, i.e. in both SAS and SAS macro. No
problem anywhere.
%* something ;
was a comment inside macro and illegal in open code. No problem when the
single and double quoting scandals are not operative.
* something ;
was flotsam and jetsam in a macro program to be passed on to the SAS
compiler where it was treated as a comment, just as the same code would be
when outside of macro. No inherent problem, but it does require a good deal
of understanding.
Consider
58 %macro w ;
59 /* not all comments are equal */
60 * simple data step ;
61 data w ;
62 x = 1 ;
63 run ;
64 %mend w ;
65
66 options mprint ;
67 %w
MPRINT(W): * simple data step ;
MPRINT(W): data w ;
MPRINT(W): x = 1 ;
MPRINT(W): run ;
Note that the first comment is not passed to the MPRINT. Of course not, it
is a comment. The second comment however is passed to MPRINT. That was the
way the system was intended. It gives one the ability to distinguish
comments on macro instructions, which should be in the macro but not in it's
execution, and comments on the SAS instructions which should show with the
generated code for the benefit of anyone reading the SAS log and in need of
comments about the generated code.
This system also allows one to generate comments just like code. For
example,
81 %macro w ;
82 %local i j ;
83 /* not all comments are equal */
84 * %do i = 1 %to 5 ;
85 simple, %do j = 1 %to &i ; very %end ; simple data step
86 %end ;
87 ;
88 data w ;
89 x = 1 ;
90 run ;
91 %mend w ;
92
93 options mprint ;
94 %w
MPRINT(W): * simple, very simple data step simple, very very simple data
step simple, very
very very simple data step simple, very very very very simple data step
simple, very very very
very very simple data step ;
MPRINT(W): data w ;
MPRINT(W): x = 1 ;
MPRINT(W): run ;
Neat, I like the idea, although I admit I have never found the need to use
it before; it gives me confidence that the system is well designed and
consistent.
However, many people like *-comments and were used to using them when they
wrote SAS code. So when they started writing macro code they soon
complained about the fact that sometimes there habit caused trouble and
wanted the system cured rather than there habit. As you might imagine it
presents a real difficulty because you cannot consistently support both FACT
1, FACT 2, and have *-comments treated as SAS statements, and comments in
both SAS macro and macro.
Here is the conflict.
97 %macro me;
98 %put Macro Running!;
99 %mend me;
100 %macro q ;
101 * %put ========== ;
102 * %me ;
103 * %put ========== ;
104 %mend q ;
105 %q
==========
MPRINT(Q): * * %me ;
==========
MPRINT(Q): *
Note that the %PUT statements executed and that the semicolons are owned by
the %PUT statements. Hence the double semicolon before %ME and now
semicolon after the third asterisk. That should be a time bomb waiting to
go off when the next line of code is submitted. However it isn't.
106 data w ;
107 x = 1 ;
108 run ;
NOTE: The data set WORK.W has 1 observations and 1 variables.
NOTE: DATA statement used:
real time 0.04 seconds
Now we have the ugly fact that sometimes SI will sometimes end a statement
for you and sometimes it will not. Is it any wonder they don't want to
illuminate this dark corner with documentation?
Note that the user outcry has so far created a system where %DO is a macro
instruction demanding execution even inside generated comments while %ME is
not. In short %ME, is a second class macro instruction. The matter gets
worse with
109 * %put is this a comment? ;
110 * Well sometimes ;
(Does the blank line between 109 and 110 indicate that the %PUT partially
executed? I don't know.) So a %PUT in a * statement in open code is not a
macro instruction, while the %PUT in the same statement is a macro
instruction when it is inside a macro. Perhaps this should be a monument to
showing that SI is so strong on CRM that they are willing to produce and
inconsistent system in order to please their customers, or a monument to the
chaos caused when one fails to educate the customer.
Now as for your question? When you issued %BAD did the system forget to
insert a semi-colon for you or did you forget to end bad a macro call with a
semicolon? (I find it more and more annoying that SI is gradually
developing a system where one should add spurious semi-colons simply to
please the various cooks. For example, my good and valid code often has the
first word in SAS instructions in red in the enhanced editor. Or more
importantly, RSUBMIT will not be recognized unless there is a preceeding
semicolon in the physical file.)
NOTE: SCL source line.
111 %bad /* call to non-existing macro creates error msg */ ;
-
180
WARNING: Apparent invocation of macro BAD not resolved.
ERROR 180-322: Statement is not valid or it is used out of proper order.
112 * %me ; /* macro IS invoked inside comment */
113 * seems to be a comment here ;
Only you can answer that question.
Fortunately, I never developed an appetite for *-comments. Hence, it has
been no hardship for me simply avoid them and the inherent can of worms that
they have wrought since version 5, except when I have to work with someone
else's code. In some areas SI is pretty good on compatibility, but this is
one area where they feel free to (and perhaps are now required to) blow with
the wind. So any conclusions you come to from the above execution of SAS
8.2 may or may not be true in older versions and future versions. I do not
like to be arbitrarily restricted in the style of code I write, but this is
one area into which I will not go.
In general I see the log as a factual report of what was generated, and
comments as belonging with the generating code. Hence the restriction has
not been a great imposition for me. However, there is little wrong with the
more sophisticated rule - never allow macro instructions, and I include
macro invocation as macro instructions, between an asterisk and the closing
semi-colon. It is not nice to make a rule macro cannot appear in a SAS
statement, but these statements are just comments after all, so it should
not a big deal.
IanWhitlock@westat.com
PS. If you search the archives, you should find some previous comments I
have made on comments. Unfortunately, I do not remember how far back you
should go or to which versions they pertain.
-----Original Message-----
From: Quentin and Amanda McMullen
[mailto:qandamcmullen@POP.MAIL.RCN.NET]
Sent: Sunday, November 24, 2002 12:32 AM
To: SAS-L@LISTSERV.UGA.EDU
Subject: macro resolution inside *-comments
Hi All,
Some time ago (v6.12?), I think I was of the mind that macro references
could be resolved inside of *-comments.
More recently I had thought that *-comments would hide both macro variables
and macro invocations from the macro processor. Then tonight I stumbled
across the following. It seems that if I attempt to call a macro that does
not exist, and in the next statement have a *-comment that includes inside
a macro variable or macro name, the macro processor will see the macro
instruction.
I submitted the code below (v8.2 Win XP):
%macro me;
%put Macro Running!;
%mend me;
* %me ; /* macro not invoked inside comment */
%bad /* call to non-existing macro creates error msg */
* %me ; /* macro IS invoked inside commment */
%let mvar=I resolved1;
* &mvar ; /* macro var not resolved inside comment */
%bad /* call to non-existing macro creates error msg */
* &mvar ; /* macro var is sort of resolved inside comment (i.e. macro
reference disappears) */
%bad /* call to non-existing macro creates error msg */
* &mvar2 ; /* attempt to resolve non-existing macro var inside comment,
generates err msg */
And was surprised to see that in each line following a call to %bad, SAS
looks inside of the *-comment and invokes the macro, or tries to resolve
the macro variable. The log is below (pretty hard to read).
1 %macro me;
2 %put Macro Running!;
3 %mend me;
4
5 * %me ; /* macro not invoked inside comment */
6 %bad /* call to non-existing macro creates error msg */
_
_
_
180
180
180
WARNING: Apparent invocation of macro BAD not resolved.
ERROR 180-322: Statement is not valid or it is used out of proper order.
ERROR 180-322: Statement is not valid or it is used out of proper order.
ERROR 180-322: Statement is not valid or it is used out of proper order.
7 *
Macro Running!
7 ! %me ;
7 ! /* macro IS invoked inside commment */
8
9 %let mvar=I resolved1;
10
11 * &mvar ; /* macro var not resolved inside comment */
12 %bad /* call to non-existing macro creates error msg */
_
_
_
180
180
180
WARNING: Apparent invocation of macro BAD not resolved.
ERROR 180-322: Statement is not valid or it is used out of proper order.
ERROR 180-322: Statement is not valid or it is used out of proper order.
ERROR 180-322: Statement is not valid or it is used out of proper order.
13 * &mvar ;
WARNING: Apparent invocation of macro BAD not resolved.
WARNING: Apparent symbolic reference MVAR2 not resolved.
13 ! /* macro var is sort of resolved inside comment (i.e. macro reference
13 ! disappears) */
14
15 %bad /* call to non-existing macro creates error msg */
_
_
_
180
180
180
ERROR 180-322: Statement is not valid or it is used out of proper order.
ERROR 180-322: Statement is not valid or it is used out of proper order.
ERROR 180-322: Statement is not valid or it is used out of proper order.
16 * &mvar2 ;
16 ! /* attemps to resolve macro var inside comment, generates err msg */
ERROR: Errors printed on page 1.
ERROR: Errors printed on page 1.
ERROR: Errors printed on page 1.
2 The SAS System 00:17 Sunday, November 24, 2002
NOTE: SAS Institute Inc., SAS Campus Drive, Cary, NC USA 27513-2414
NOTE: The SAS System used:
real time 0.37 seconds
cpu time 0.37 seconds
;
Kind Regards,
--Quentin