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 (September 2006, week 1)Back to main SAS-L pageJoin or leave SAS-L (or change settings)ReplyPost a new messageSearchProportional fontNon-proportional font
Date:         Tue, 5 Sep 2006 20:51:02 +0000
Reply-To:     iw1junk@COMCAST.NET
Sender:       "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From:         Ian Whitlock <iw1junk@COMCAST.NET>
Subject:      Re: making code generic
Comments: cc: Arjen <a.benedictus@GMAIL.COM>

Subject: making code generic Summary: Short macro lesson in the role of lists Resondent: Ian Whitlock

Arjen,

You seem to be looking general for ways to manipulate lists. That is a very wise idea leading to a solid kernel of macro problems. The code below doesn't give a general answer, but it does give the tools to tackle your example problem in a general form.

Let's assume you have a long array of macro variables, holding variable names, and want to obtain a subinterval of these names. Consider

%macro maclist ( root = d , start = 7 , stop = 11 ) ; %* convert sequence of macro variable values to a list *; %local i list ; %do i = &start %to &stop ; %let list = &list &&&root&i ; %end ; &list %mend maclist ;

%let d7 = x ; %let d8 = y ; %let d9 = z ; %let list1 = %maclist(root=d, start=7, stop=9) ; %put list1 = &list1 ;

Now consider the problem of prefixing an underscore to a list of variable names.

%macro preflist ( list = , pref = _ ) ; %* preface each element of &LIST with &PREF *; %local i newlist ; %do i = 1 %to &sysmaxlong ; %if %length(%scan(&list,&i)) = 0 %then %goto endloop ; %let newlist = &newlist &pref.%scan(&list,&i) ; %end ; %endloop: &newlist %mend preflist ;

%let list2 = %preflist(list=&list1, pref=_) ; %put list2 = &list2 ;

Then your code (untested) reduces to

%let list1 = %maclist(root=d, start=7, stop=11) ; %let list2 = %preflist(list=&list1, pref=_) ; data Have7 (drop=i &list2); set Have7; array nn [*] &list2; array cc [*] $ &list1; do i = 1 to dim(nn); cc[i] = put (nn[i], results.); end; run;

I hope this example illustrates to you the general power of list making tools and their role in writing general macro programs.

In 2003 Quentin McMullin and I created a beginning macro course for NESUG consisting of 15 example programs and a few appendices. (In the presentation I think we barely managed to give 4 or 5 of the programs.) The last example was written by Quentin. (Actually Quentin wrote and tested all the examples, I just specified some of them.) He considered the general problem of converting a list of character variables in a data set to numeric variables with the same names. The example provided a simple illustration of combining several macros to solve a problem.

You might be able to locate the course at the NESUG site. Since the conversion is a frequent SAS-L problem and Quentin was quite taken with his solution, you might find his code in a SAS-L message or a Coder's Corner paper at some SUGI or NESUG conference. There must also be many others that have looked at the conversion problem in general. It would not surprise me to find out that there is a solution at http://support.sas.com/.

Take a look at http://lexjansen.com/sugi/ as a great SAS search tool.

For comparison (since he offered it), if you have SCL available, you might see how much help you can get from the true believer Joe Whitehurst with an SCL solution to your problem, and then report back to SAS-L your experience. I am sure that some would be interested.

Ian Whitlock ================= Date: Mon, 4 Sep 2006 09:42:39 -0700 Reply-To: Arjen <a.benedictus@GMAIL.COM> Sender: "SAS(r) Discussion" From: Arjen <a.benedictus@GMAIL.COM> Organization: http://groups.google.com Subject: making code generic Comments: To: sas-l Content-Type: text/plain; charset="iso-8859-1" Hello SAS-L, I have the following code (see below). The format Results converts numeric data into character data (see my postings last week). The macro variables refer to sas data set variables in Have7 with all different names (lab tests, medical examinations). How can I make my code more generic? That is, suppose I have data set Have21 with variables referred to as &d34 to &d39, then would it be possible that I don't have to enter all the numbers again but (for instance) only specify the interval? Specifying the interval _&d7-_&d11 does not work because these macro variables refer to real variables that don't contain numeric indicators. data Have7 (drop=i _&d7 _&d8 _&d9 _&d10 _&d11); set Have7; array nn [1:5] _&d7 _&d8 _&d9 _&d10 _&d11; array cc [1:5] $ &d7 &d8 &d9 &d10 &d11; do i = 1 to 5; cc[i] = put (nn[i], results.); end; run; Thanks for your suggestions, have a nice evening, Arjen


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