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 (October 2009, week 2)Back to main SAS-L pageJoin or leave SAS-L (or change settings)ReplyPost a new messageSearchProportional fontNon-proportional font
Date:         Tue, 13 Oct 2009 19:05:40 -0500
Reply-To:     Joe Matise <snoopy369@GMAIL.COM>
Sender:       "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From:         Joe Matise <snoopy369@GMAIL.COM>
Subject:      Re: %FOR Macro Release 2.0 - It's Simplified and Objectified
Comments: To: "Anderson, James" <James.Anderson@ucsf.edu>
In-Reply-To:  <379A927A452F3D43A3C8705F4E67905F0CE84E4925@EX05.net.ucsf.edu>
Content-Type: text/plain; charset=ISO-8859-1

I see no reason to 'show my code' for any of your strawmen; certainly there are things that %for can do in fewer lines of code than I could write them. If you read my post, you'd understand that I could care less about lines of code. I care about readability and efficiency, and writing data-driven code.

When I write code to do (well, anything), the hope is that any SAS programmer of moderate ability could read the code and understand what it's doing, without prior knowledge [except for job-specific knowledge, of course]. Writing four lines of code to accomplish a trivial purpose is quaint, but useless for actual programming.

If you really want a short bit of code to split sashelp.class on age, here you are...

proc sort data=sashelp.class nodupkey out=ages; by age; run; data _null_; set ages; call execute(cats("data age_",age,"; set sashelp.class(where=(age=",age,")); run;"); run;

One more line of code, which is implicit from yours, and clearer what it is doing to someone who understands SAS but has not encountered your macro.

Or, proc sql; select distinct cats("data age_",age,"; set sashelp.class(where=(age=",age,")); run;") into :runlist separated by ' ' from sashelp.class; quit; &runlist

Four lines still, no PROC SORT needed, and again, readable by someone who understands SAS with no further knowledge.

SAS is wonderful in that it has a multitude of ways to do any given thing. That doesn't mean you should use all of them...

I don't even remotely understand how your macro does thing #3 (without having read your macro code); certainly it doesn't seem like a truly generic utility macro could do that given the minimum data you provided it. How you derive subfolderpath from topfolderpath is entirely unclear, if you put something in the macro to derive file paths from higher-up file paths, then you've left the realm of generic utility macro, and are now writing a catch-all do-everything macro.

However, the SAS code for doing this is surprisingly simple... I define my name [shortname] in a particular way, that may or may not be appropriate for the particular situation - but the advantage of writing it out is that you can do so in a way appropriate to your methodology. I put the PROC IMPORT code into a macro and in a direct statement, to show both ways [for those who prefer one or the other].

%let topfolderpath=c:\temp\; %let xlext=xls;

%macro import(dir,name,xlext); proc import file="&dir" out=&name dbms=excel replace; run; %mend import;

filename dirlist pipe "dir &topfolderpath.\*.&xlext /s/b "; data _null_; infile dirlist truncover; input @1 str $500.; put str=; name=compress(scan(str,count(str,'\')+1,'\'),,'KFD'); put name=; call execute(cats('%import(',str,',ds_',name,',',"&xlext",')')); call execute(cats('proc import file="',str,'" dbms=excel replace out=ds_',name,'; run;')); run;

Hardly something requiring a utility macro to accomplish. I think it's remarkable how often people forget that there's a handy loop available in SAS, known as the data step, that can do anything a macro %do loop can and more...

-Joe

On Tue, Oct 13, 2009 at 5:58 PM, Anderson, James <James.Anderson@ucsf.edu>wrote:

> Hi Joe, > > You've made a lot of general comments without responding to the problems > taken from SAS-L that I posted. The first problem was: > > "Split dataset sashelp.class into separate datasets by the age variable" > > Here's my code: > > proc sort data=sashelp.class nodupkey out=ages; by age; run; > > data %for(age, in=[ages], do=%nrstr(class_&age(where=(age=&age)))); > set sashelp.class; > run; > > Please show yours. > > >> People use macros as functions, when they're simply not. > > Macros are compile-time functions. They also can be used for global flow > control. > The third problem taken from SAS-L that I posted demonstrated this: > > "Import all spreadsheets in all subfolders of a top folder" > > Here's my code: > > %let topfolderpath= ... path to some directory ... ; > %for(filepath, in=<&topfolderpath>, do=%nrstr( > %let subfolderpath=&filepath; > %for(filepath shortname, in=<&subfolderpath>, do=%nrstr( > proc import datafile="&filepath" out=&shortname > dbms="excel" replace; > run; > )) > )) > > Please show yours. > > Thanks, > > Jim > --- > From: Joe Matise [mailto:snoopy369@GMAIL.COM] > Sent: Tuesday, October 13, 2009 12:38 PM > Subject: Re: %FOR Macro Release 2.0 - It's Simplified and Objectified > > Jim, > The issue is not with OOP. OOP is wonderful, and allows all sorts of > simplification to code and focus on keeping things where they should be, > neat, organized, and readable. > > %FOR macro does not do that, though. It makes the code harder to read, > less > efficient, and does in a macro what is simpler to do in properly written > data step code. > > I have no problem whatsoever with macros, and I think that plenty of other > people in your 'some of you folks' list will fall in that category as well. > I write a good portion of my code in macros. Anything I do twice or more, > goes into a macro, because that way it is only maintained once. > > However, macros do *not* take the place of functions. That's the problem > that I have, and I'd guess many others do as well. People use macros as > functions, when they're simply not. Using macro code to emulate functions, > in the sense of using %do, %if, etc. in order to repetitively execute code, > is in most circumstances not only inefficient, but difficult to read and > comprehend what is going on; and further, it separates the code from the > data, which is not a good thing in SAS, being a data-driven language. I > couldn't count how many times we get someone asking how to split their code > up with macros to execute once on each kind of group, when the correct > answer is to run the code once with BY groups. Looping the same code over > the dataset will take far longer, and be much more difficult to maintain, > than running it with BY groups. > > I think the idea of using macro looping to organize things this way is, in > fact, entirely counter to the point of object-oriented programming. It > does > not increase the efficiency of the program, the readability of the program, > or the 'neatness' of the program. It may or may not decrease the lines of > written code, but I'd venture to guess that it doesn't even do that much of > the time, and I couldn't care less about a few lines here or there - if > it's > more maintainable and more efficient, it is better code. It may be > technically 'object oriented', but I'd suggest that SAS code should have > 'data oriented' as its goal, not 'object oriented'. Data driven programs, > as compared to programs with much of the programming logic built inside the > macro language itself, are similar to the comparison between an > object-oriented C++ program, and an old-style function-oriented C program, > in my mind... > > If you want to write an 'object oriented' program, may I suggest C++? Or > C#? Trying to shoehorn an idea that simply is inappropriate for the > language, and failing to understand the basic philosophy behind the idea, > is > a mistake. > > -Joe > > On Tue, Oct 13, 2009 at 12:05 PM, Anderson, James > <James.Anderson@ucsf.edu>wrote: > > > Some of you folks seem to dislike macros. Do you also dislike functions? > > Do you compute square-root with a newton-raphson iteration in a data > step? > > > > Technology is scaled up by encapsulating complexity. > > > > Object-oriented programming has shown the practicality of looping over > > different kinds of things with the same statements. The code is smaller, > > more consistent, and lets you concentrate on the problem being solved, > > rather than the mechanics of looping. On my sascommunity.org piece, I > > solved 3 problems from SAS-L in less code than anyone has done so far > and > > gave a similar look to solutions to very different problems. Take a look > at > > the %for macro from that perspective - you might find it useful . > > > > Regards, > > > > Jim > > > > -----Original Message----- > > From: Tom Abernathy [mailto:tom.abernathy@GMAIL.COM] > > Sent: Monday, October 12, 2009 12:56 PM > > Subject: Re: %FOR Macro Release 2.0 - It's Simplified and Objectified > > > > This %FOR macro reminds me of my first programming job back in 1979. > > We were using assembly code for the Z-80 microprocessor. We wrote our > > programs using a macro assembler. Another new college grad was > > working on part of the system. He liked to use PL/1 so he wrote a > > series of macros that made it so he could write his code as if it was > > PL/1. The resulting code didn't fit in the memory on the system, run > > too slow and no one could understand it. > > > > Needless to say one of the senior programmers had to totally rewrite > > that section of the project. > > > > - Tom Abernathy > > > > On Oct 11, 1:10 pm, j...@STANFORDALUMNI.ORG (Jack Hamilton) wrote: > > > Calling it object-oriented doesn't mean that it is. > > > On Oct 10, 2009, at 12:04 pm, xlr82sas wrote: > > > > On Oct 10, 3:42 am, "nina" <s...@mailinator.com> wrote: > > > >> shorter link to samehttp://20.fi/2843 > > > > > >


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