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 2002, week 2)Back to main SAS-L pageJoin or leave SAS-L (or change settings)ReplyPost a new messageSearchProportional fontNon-proportional font
Date:         Thu, 12 Dec 2002 11:14:25 -0500
Reply-To:     Ian Whitlock <WHITLOI1@WESTAT.COM>
Sender:       "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From:         Ian Whitlock <WHITLOI1@WESTAT.COM>
Subject:      Re: recruiting cheesy, sleasy SAS tricks
Comments: To: "Howard_Schreier@ITA.DOC.GOV" <Howard_Schreier@ITA.DOC.GOV>
Comments: cc: "michael@BASSETTCONSULTING.COM" <michael@BASSETTCONSULTING.COM>
Content-Type: text/plain; charset="iso-8859-1"

Howard,

When I first read Rolland's message, I had much the same thought, but without the cute reference to Art's seminal papers. So I was glad to see you express the thought.

I did not reply, in part, because I am in a bit of a bind. I sometimes want to use a format in a macro. I want to construct it once, but not every time the macro is called. So I do pretty much the same thing, I create a file.

%macro usefmt ; %*code ; %mend usefmt ;

proc format ; *format code ; run ;

This works fine as an include file or in an autocall library as long as USEFMT is invoked on a step boundary. This has not been a problem for me because USEFMT has by its nature been restricted to such invocations. So, have I crossed that fine line or is the above a legitimate technique? If you consider this form legitimate then what makes the difference?

Now having given the matter more serious thought, I would like to see you explicate exactly where the line lies after considering the following thoughts.

Just yesterday Fabio [faga77@LIBERO.IT] raised questions about the code

> data output;do until (last.group); > set input;by group; > output; > lvar = var; > end; > run;

Although it was a problem for him, it is quite reasonable to make an assignment after the OUTPUT statement in preparation for the next iteration of the loop. I hope we both agree that there is nothing sleazy about this control structure and no line has been crossed here. To avoid any doubt look at another example from macro code. I often use the following technique in marching through a list.

%let i = 1 ; %let word = %scan ( &list , &i ) ; %do %while ( %length(&word) = 0 ) ; %* do something with &word ; %let i = %eval ( &i + 1 ) ; %let word = %scan ( &list , &i ) ; %end ;

(I would love to see the macro language expanded with a construct that could eliminate the need for so much control code for such a simple idea.)

Again we see the change in entities after the action to prepare for the next iteration of the loop. Can you make a clear distinction of why this code is on one side of the line and Rolland's suggestion is on the other?

I too have an aversion to global variables and therefore always want to seek out ways to avoid their necessity. For me Rolland's problem just illustrates the classic necessity for static local variables to handle this problem. I do wish that SI would see the need for them and implement them in macro. With that tool I would consider it by far the best solution to the problem.

However, we do not currently have local static variables, so what can one do? Here is code to achieve the same purpose. It will work either as an include file or in an autocall library.

%macro __rolland ; %put Hurrah for Rolland! ; %mend __rolland ;

%macro r ; %__rolland ; %* ready to clobber __rolland ; %macro __rolland ; %put Macro __rolland is limited to one execution ; %mend __rolland ; %mend r ;

Here is the test code.

%r %r

Now my question is, with this form have I stepped back onto the respectable side of the line or not? To me it meets the conditions of the looping problems presented above. The macro __ROLLAND is prepared before the action then used and cleaned up after the use. Thus it should be considered well within the nature of normal programming structures. However, I admit that I am doubtful enough to welcome your opinion.

Perhaps the precise position of that line depends on the adequacy or inadequacy of the tools we have to solve the problem.

After further consideration of Rolland's message I see that without using two macros the trick does not work. So perhaps my unease was really with his inadequate treatment of the problem rather than the basic idea.

Part of Art's genius was to stay far enough away from the line that there could be no doubt.

Michael, you better not be sleazy about the way you test the sleaze you are collecting.

IanWhitlock@westat.com

-----Original Message----- From: Howard_Schreier@ITA.DOC.GOV [mailto:Howard_Schreier@ITA.DOC.GOV] Sent: Wednesday, December 11, 2002 12:44 PM To: SAS-L@LISTSERV.UGA.EDU Subject: Re: recruiting cheesy, sleasy SAS tricks

It seems to me that there is a fine line between "cheesy, sleasy" and Art Carpenter's "Programming for Job Security".

On Wed, 11 Dec 2002 12:36:30 -0000, Roland <roland@RASHLEIGH-BERRY.FSNET.CO.UK> wrote:

[snip]

>And another one, a dummy macro declaration. This is a very cheesy and sleazy >trick. It is for when you want to run a macro once but never again during a >session. Sure, you are going to call it maybe dozens of times, but you do >not want to run it if it has already been run. You could set up a global >macro variable and test its setting and branch out of the macro, but that >wouldn't be either cheesy or sleazy. So what you do instead (and I think >this only works for members of an autocall library) is to put all the macro >code before the macro declaration. and just end the macro with: > >%macro mymacro; >%mend mymacro; > >So all the macro code gets run and the stored macro contains nothing. That >way you call it as many times as you like afterwards and it will do nothing.

[snip]


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