LISTSERV at the University of Georgia
Menubar Imagemap
Home Browse Manage Request Manuals Register
Previous messageNext messagePrevious in topicNext in topicPrevious by same authorNext by same authorPrevious page (December 2005, week 2)Back to main SAS-L pageJoin or leave SAS-L (or change settings)ReplyPost a new messageSearchProportional fontNon-proportional font
Date:         Thu, 8 Dec 2005 20:21:07 +0000
Reply-To:     toby dunn <tobydunn@HOTMAIL.COM>
Sender:       "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From:         toby dunn <tobydunn@HOTMAIL.COM>
Subject:      Re: Macro quoting essentials
Comments: To: lzhang9830@YAHOO.COM
In-Reply-To:  <1134067306.664342.61860@g47g2000cwa.googlegroups.com>
Content-Type: text/plain; format=flowed

Lei,

The problem that I have always saw with creating marcro definitions that use pbuff or parmbuff (which ever you choose to call it) is that it leads to bad macro design. Essentually what you end up with is some secret contract with the rest of the code and the macro.

Admitedly using at the very least a positional parameter in the definition is better than none at all (but not by much) positional parameters still should not be used IMHO.

Consider: Slightly modified from SAS Online Doc:

%macro printz(x) / parmbuff; %let num=1; %let dsname=%scan(&x,&num); %do %while(&dsname ne); proc print data=&dsname; run; %let num=%eval(&num+1); %let dsname=%scan(&syspbuff,&num); %end; %mend printz;

With :

Direct copy from online doc: %macro printz/parmbuff; %let num=1; %let dsname=%scan(&syspbuff,&num); %do %while(&dsname ne); proc print data=&dsname; run; %let num=%eval(&num+1); %let dsname=%scan(&syspbuff,&num); %end; %mend printz;

Both besides sufferening from very inefficient coding mask what you are passing and what macro var you are passing it too. Thus the readability and maintainability of your code goes right down the drain. I have yet to find a problem that could only be solved by using pbuff or positional parameters.

Now aside from the secret contract if you will, you also have the macro design issue:

Lets start with the above example :

%macro printz/parmbuff; %let num=1; %let dsname=%scan(&syspbuff,&num); %do %while(&dsname ne); proc print data=&dsname; run; %let num=%eval(&num+1); %let dsname=%scan(&syspbuff,&num); %end; %mend printz;

Okay as I see it there are several things wrong here no declaring the macro vars local or global (local is prefered). %let this %do that heck my head starts to hurt just looking at it.

A simpler solution is as follows:

%macro printz (DSNList = ) ; %local I Stop ;

%let Stop = %eval( %sysfunc( countc(&DSNList , ',') ) + 1 ) ;

%do I = 1 %to &Stop ;

proc print data = %scan(&DSNList , &i , ',') ; run ;

%end ;

%mend Printz ;

%printz(DSNList = %str(Red , Blue, Green) )

Now the Programmer who is calling the macro knows that he has commas in thier text string and that is I think the right place to put the quoting.

On the other I seriuosly doubt that pbuff was ever truelly intended for the person who hard codes a list of values iin but rather the programmer who dynamically gets it from a list.

So to that end I say that a macro definition may be the wrong tool for the job:

Data Colors ; length color $5 ;

do I = 1 to 5 ; Color = 'Red' ; output ; end ;

do I = 1 to 8 ; Color = 'Blue' ; output ; end ;

do I = 1 to 11 ; Color = 'Green' ; output ; end ;

run ;

proc sort data = Colors ; by Color ; run ;

data _null_ ; set Colors ; by color ;

if first.color then do ;

call execute('proc print') ; call execute('data = '||color||';') ; call execute('run;') ;

end ;

run ;

Toby Dunn

From: Lei Zhang <lzhang9830@YAHOO.COM> Reply-To: lzhang9830@YAHOO.COM To: SAS-L@LISTSERV.UGA.EDU Subject: Re: Macro quoting essentials Date: Thu, 8 Dec 2005 10:41:46 -0800 Hi, Toby, You are right ! The result from the %length macro function in my post should be 4 instead of 3.

I didn't track the discussion about macro quoting. I think Ian has given an excellent summary about when or how to use macro quoting functions. It is a very good guideance for most of SAS programers who are writing or using SAS macros.

The reason that I say %length is a very special macro function with any number of commas is that few people know that %length is a special vararg macro that can take any number of macro parameters, including commas. The other similiar build-in macro function are %quote, %nrbquote, %sysfunc(cat(...)),, etc. People can even develop their own vararg macros that take any number of parameters without any problems. This can be done with macro option pbuff. For example, %macro test(X)/pbuff; %put &x; %mend; You can call this macro like %test(x1, x2, x3) or %test(x1, x2, x3, x4, x5) %test won't complain at all that you have assigned more parameters that you defined.

This also remind me that if people develop vararg macros with pbuff options, they most likely will use %quote, %nrbquote macro functions in the implementation, they are, however, not necessary because we alreadly have so many %Q- macros at hand.

Have fun with vararg macros !

Lei


Back to: Top of message | Previous page | Main SAS-L page