```Date: Thu, 2 Mar 2000 11:39:13 -0500 Reply-To: "Fehd, Ronald J." Sender: "SAS(r) Discussion" From: "Fehd, Ronald J." Subject: Re: recursive macros?? Comments: To: "dmclerra@fhcrc.org" Content-Type: text/plain; charset="iso-8859-1" > From: dmclerra@fhcrc.org [mailto:dmclerra@fhcrc.org] > [snippage happens] > Which all goes to prove that if you want to take a foot off of a 2x4, > you are better off using a saw than using sandpaper. Good, we've already got the word: Clue-by-four. > That does not > make sandpaper any less useful. In this analogy, it is the wrong tool > for the job, just as recursion is the wrong tool for the fibonacci > series. We still do not need to throw away the sandpaper, and we do > not need to throw away recursion. > > Let me suggest a situation in which recursion may be a useful tool. > I recently had to program a permutation test. This required nested > DO loops. At the innermost level of nesting, I am required to perform > some action. Then I need to back out of all of the loops with END > statements. The code Paul Kairis provided is quite similar to my > requirements, except that Paul's code doesn't attempt to do anything > more than just demonstrate that one can recurse. Consider the code > below: > %macro recur(maxdepth=, loop=); > /* Code to execute in every loop. Initiate DO loop! */ > do i&loop=-1 to 1 by 2; > /* Code to execute only in innermost loop. */ > %if &loop=&maxdepth %then %do; > selected = sum(%do j=1 %to &maxdepth; %if &j>1 %then ,; > i&j%end;); > if selected=sum_int then do; > ncomb = ncomb + 1; > sel_row = %do j=1 %to &maxdepth; %if &j>1 %then || ; > i&j %end; ; > permute[ncomb,] = sel_row; > end; > %end; > /* Control recursion. */ > %let next=%eval(&loop + 1); > %if &next<=&maxdepth %then %recur(maxdepth=&maxdepth, loop=&next); > /* Code to execute in every loop. End DO loop! */ > end; > %mend recur; Yep, I can see that this works. Now, who else do you work with, that can see that this works? Recursion is a powerful tool. And recursion's place is in languages that directly support it. I did my toy programs in college and I know and understand that the concept works. Anyone's tests of SAS support of recursion to the contrary, and someone, besides me, will find a definitive statement in support of or to the contrary in the SAS documentation won't necessarily convince me that SAS supports recursion. Let me state that clearly: either it does or it doesn't. My not so humble opinion is that it doesn't. And if it did, it would take good programmers, like Dale appears to be, to use that functionality well. There is a discipline related to recursion. It first involves the conception of an algorithm that could be implemented w/recursion. See the textbooks. Name another example besides the fibonacci series? Implementing the algorithm in the language of choice is the second step. Third, we have to eliminate recursion, when and where it is inappropriate. So that's the college drill. Now we're showing up for our regularly scheduled 40/hr/week. We want to write code, quickly, efficiently, and THAT OTHER PEOPLE CAN MAINTAIN. besides ourselves. Unless we want Permanent Job Security(tm). Well, I got it; I was warned about this in my Assembler class: Never write undocumented [insert language of choice] code, if you want to rise in your profession, because you'll never be promoted out of a job where you are the only one who knows how an indespensible program works. So, this discussion is me expressing my opinions about job security, not whether or not SAS supports recursive macros. > Now if I invoke macro recur with maxdepth=10 and loop=1, it writes the > following (IML) code (extracted from the log with MPRINT on): > do i1=-1 to 1 by 2; > do i2=-1 to 1 by 2; > do i3=-1 to 1 by 2; > do i4=-1 to 1 by 2; > do i5=-1 to 1 by 2; > do i6=-1 to 1 by 2; > do i7=-1 to 1 by 2; > do i8=-1 to 1 by 2; > do i9=-1 to 1 by 2; > do i10=-1 to 1 by 2; KISS: Keep It Simple and Straigtforward: %DO I = 1 %TO &DEPTH.; do i&I.= -1, 1; %END; > selected = sum( i1 , i2 , i3 , i4 , i5 , i6 , i7 , i8 , i9 , i10); > if selected=sum_int then do; > ncomb = ncomb + 1; > permute[ncomb,] = sel_row; %DO I = 1 %TO &DEPTH.; end; %END; > end; > end; > end; > end; > end; > end; > end; > end; > end; > end; > end; > > > The recursive macro completed all of my do loops for me. Without > recursion, my code would have required two macro DO loops, one which > created the DO I&I statements and one which created the END > statements. > Sandwiched inbetween these two sets of macro DO loops would be the > code to execute in the innermost loop. >There is considerable elegance to the recursive approach. I agree, because I have a B.S. in Comp Sci., and have studied such. Others, w/out such training, may disagree. > Now, if I could understand macro quoting > well enough to pass the macro code which needs to be executed in the > innermost loop, I would have a really nifty recursion macro. > > Maybe you can help me with that, Ron Fehd the macro maven! Sorry, I got side-tracked on the job security issue. macro quoting? Yeow! I know reasons not to go there, too! LOL Ron Fehd the macro maven CDC Atlanta GA USA RJF2@cdc.gov ---> cheerful provider of UNTESTED SAS code!*! <--- ```

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