Art:
I understand what you're saying, but I think the developers were true to the fundamental nature of the macro facility when they built in that behavior. A SAS macro program can generate entire multi-step progarms, single step programs, parts of steps, entire statements, parts of statements or a single character. Whether or not you put a semi-colon in your macro program, especially when you are generating parts of statements really, really depends on what you are trying to have be resolved into code.
The SAS Macro facility doesn't technically "execute" anything and when a macro program is invoked, it doesn't technically "execute" it only resolves macro triggers and macro variable references and after it is done with all the resolving and building of code, the built code goes forward to the compiler.
That's why I call the SAS Macro facility a "big typewriter" -- all it's doing is typing code for me. Which is why I ALWAYS recommend that you start with a working SAS program. If I had been writing your macro, I would have started with a working program like this:
[pre]
DATA TEST;
M1=200901;
M2=200705;
DIFF=(SUBSTR(PUT(m1,Z6.),1,4)*12 + SUBSTR(PUT(m1,Z6.),5,2)*1) -
(SUBSTR(PUT(m2,Z6.),1,4)*12 + SUBSTR(PUT(m2,Z6.),5,2)*1 ) ;
RUN;
[/pre]
The semi-colon at the end of the assignment statement is the ONLY semi-colon that's needed. So, if I am writing a macro program to "type" this for me (shown once for M1):
[pre]
(SUBSTR(PUT(m1,Z6.),1,4)*12 + SUBSTR(PUT(m1,Z6.),5,2)*1)
[/pre]
...then it would be inappropriate to even put a semi-colon inside the macro program definition. If you turn on the debugging options MPRINT SYMBOLGEN and MLOGIC, you can see in the SAS log, that all the macro facility is doing is typing parts of statements to go forward to the compiler:
[pre]
978 DATA TEST;
979 M1=200901; M2=200705;
980 DIFF=%FUNC(M1)-%FUNC(M2);
MLOGIC(FUNC): Beginning execution.
MLOGIC(FUNC): Parameter MONTH has value M1
SYMBOLGEN: Macro variable MONTH resolves to M1
SYMBOLGEN: Macro variable MONTH resolves to M1
MPRINT(FUNC): SUBSTR(PUT(M1,Z6.),1,4)*12 + SUBSTR(PUT(M1,Z6.),5,2)*1 < -- here
MLOGIC(FUNC): Ending execution.
MLOGIC(FUNC): Beginning execution.
MLOGIC(FUNC): Parameter MONTH has value M2
SYMBOLGEN: Macro variable MONTH resolves to M2
SYMBOLGEN: Macro variable MONTH resolves to M2
MPRINT(FUNC): SUBSTR(PUT(M2,Z6.),1,4)*12 + SUBSTR(PUT(M2,Z6.),5,2)*1 < -- and here
MLOGIC(FUNC): Ending execution.
981 RUN;
[/pre]
And these days, with PROC FCMP, I probably wouldn't do this type of thing in a macro program anyway. Truth be told, if all I wanted was the difference between 2 dates, I would have used the INTCK function.
[pre]
DATA calcdur;
M1=200901;
M2=200705;
DIFF=(SUBSTR(PUT(m1,Z6.),1,4)*12 + SUBSTR(PUT(m1,Z6.),5,2)*1) -
(SUBSTR(PUT(m2,Z6.),1,4)*12 + SUBSTR(PUT(m2,Z6.),5,2)*1) ;
put m1= m2= diff=;
date1 = input(put(m1,6.),yymmn6.);
date2 = input(put(m2,6.),yymmn6.);
month_diff = intck('month',date2,date1);
put date1= date2= month_diff=;
RUN;
ods listing;
proc print data=calcdur;
var m1 date1 m2 date2 diff month_diff;
format date1 date2 yymmn6.;
run;
[/pre]
cynthia