Date: Fri, 6 Dec 2002 09:27:33 -0500
Reply-To: "Fehd, Ronald J. (PHPPO)" <rjf2@CDC.GOV>
Sender: "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From: "Fehd, Ronald J. (PHPPO)" <rjf2@CDC.GOV>
Subject: Re: tip macro function SymChk
Content-Type: text/plain
> From: Ian Whitlock [mailto:WHITLOI1@WESTAT.com]
> I assume you lost the formatting and introduced the mistakes
> in Art's version of the SYMCHK macro.
<sigh> those floating semicolons
... musta been the bifocals B-)
%macro SYMCHK(NAME);
%IF %nrquote(&&&NAME.) = %nrstr(&)&NAME.
%THEN %LET YESNO=NO;
%ELSE %LET YESNO=YES;&YESNO.%MEND;
%PUT 'does &tmp exist? ' %SYMCHK(TMP);
> The problem with both
> versions is the warning messages produced in the log when the
> macro variable does not exist.
Why is this a problem, Ian?
When the macro variable doesn't exist,
SAS reports that fact, the condition fails and processing continues.
If SAS went to syntax checking mode I would understand your concern.
I think that's a reasonable and not annoying side effect.
> Since you were nice enough to give the link to the SI
> solution to this problem, I took a look. Thanks.
you're welcome.
I appreciate your participation in this dialogue.
> Now one can say the macro is in a FAQ list
> and thus it need not meet high standards.
ah, yes,
I could be generous and say that this item
does at least get one off the ground,
... and stumbling.
> Or one can ask, doesn't SI have a
> responsibility to promote high standards in their public code?
given the smorgasbord of ways to type SAS statements
that SI presents in their published materials,
both paper, plastique, and electronic,
I politely suggest that SI and high programming standards in the same
sentence
approaches oxymoron.
> The first thing to hit me was no comment that the variables
> I, OB, DSID, etc. would always test as being present.
>
> Second the %LOCAL list is missing more variables than it
> includes. Then I began looking at the code more carefully.
> A lot of stuff is done in the loop that should be done
> outside the loop.
I would have UPCASEd the parameter immediately.
%LET mvar = %upcase(&mvar);
who thought up this loop control?
%do %until(&ob = -1);
%let i=%eval(&i+1);
%LET NOBS = ...;
%DO I = 1 %TO &NOBS.
%until(&ob = -1);
... anyway, enough programming critique,
that's not where I want to go with this discussion.
> How should name conflicts be resolved? SCOPE should be used
> to eliminate variable names in CHECK.
as an aside I'd be interested to see how to subset using these SCL functions
> What about the local problem in general?
I propose that a good standard would expect
that a macro explicitly declare every macro variable used
either %local, or %global, as appropriate,
This is especially important at this time
because we have SAS-L users who are still (having to be) programming
in v6, v8 and now v9. New&Improved scoping rules were introduced
between these versions.
Hu knows when SI might reverse itself -- v9.1? --
because of user complaints to TechSupport?
I would suggest that that would be good proactive programming practice,
something obviously not in the specifications
when these items were written for the FAQ.
> I think it would be
> good to develop the habit of using _abc_ (where a,b, and c
> are some letters or null and more chars may be used when
> appropriate) as a preface to all local variables. I suggest
> that the SAS Institute should claim and use _SAS_. The macro
> I present below was written following that rule. (I use _IW_
> or the macro name (possibly abbreviated) enclosed in
> underscores when I am
> being careful.)
>
> Now I suggest that
>
> %local _abc_: ;
>
> should be allowed to declare all variables beginning with
> _ABC_ to be local.
very good suggestion.
now that we have long mvar names
I propose that any macro variable beginning with the name of the macro
be local to that macro.
e.g.:
%macro ABC(...);
%DO ABC_I = 1 %TO ...;
> From my point of view this is a step backward in standards
> because I believe strongly that each local variable should be
> made explicit when possible. However, I would rather see the
> suggestion adopted and used than simply have the %LOCAL
> statement ignored.
>
> Here is the macro and tests.
>
> %macro check(_sas_mvar);
> %* Return yes when macro variable &_sas_mvar exists and no
> otherwise.
> Note that variables in the %LOCAL statement will always
> return yes.
> ;
> %local _sas_i _sas_tmp _sas_dsid _sas_num _sas_val _sas_ob
> _sas_scope
> ;
> %let _sas_dsid=%sysfunc(open(sashelp.vmacro));
> %let _sas_num=%sysfunc(varnum(&_sas_dsid,name));
> %let _sas_scope = %sysfunc(varnum(&_sas_dsid,scope));
> %let _sas_tmp = no ;
>
> %do %until(&_sas_ob = -1);
> %let _sas_i=%eval(&_sas_i+1);
> %let _sas_ob=%sysfunc(fetchobs(&_sas_dsid,&_sas_i));
> %let _sas_val=%sysfunc(getvarc(&_sas_dsid,&_sas_num));
>
> %if &_sas_val = %upcase(&_sas_mvar) %then
> %do;
> %if %sysfunc(getvarc(&_sas_dsid,&_sas_scope)) ^= CHECK %then
> %do ;
> %let _sas_ob = -1;
> %let _sas_tmp=yes;
> %end ;
> %end;
>
> %end;
> %let _sas_rc=%sysfunc(close(&_sas_dsid));
>
> &_sas_tmp
>
> %mend check;
>
> /** Check for the existence of the macro variable _sas_scope
> **/ %global _sas_scope ; %put Does the macro variable exist:
> %check(_sas_scope);
>
> %symdel _sas_scope ;
> %put Does the macro variable exist: %check(_sas_scope);
>
> %macro mac ;
> %local _sas_scope ;
> %put Does the macro variable exist: %check(_sas_scope);
> %mend mac ;
>
> %mac
>
> Of course, one might add another parameter to indicate a
> required scope.
interesting idea, that a macro might check to see if a macro variable
exists in the %global scope, and if not declare it %global.
Peter Crawford might use that in his timer routines
that we were discussing yesterday.
> I am still wrestling with the issue of
> reading long lists of variables and the time it takes.
> Does anyone have more suggestions?
While I encourage the use of underline inside mvar_names
I find them disconcerting as the first character.
If people want certain names at the top of an alphabetical list
I can understand using underline as first character,
Carrying this absurdity about as far as it can go,
we have seen recent macros posted with mvars with triple leading underlines.
Certainly anyone going to such lengths to avoid mvar name clashes
had better spend another day RTFM on scope rules.
Ian, I had hoped you would addressed the issue
of what type of value to return from such functions?
Art's example returned character strings in (YES,NO);
your example returns (yes,no).
As a practical example, while I am talking/typing to myself,
I might expect my computer named HAL to answer me in English.
"HAL, does this macro variable exist?"
'Yes'
"Fine, Then please do the following: ..."
But, I haven't arrived in the 22nd century yet,
so I would prefer to talk to SAS which instructs my Pentium 4
in binary,
thus I would expect my macro functions to respond in the geek-speak
of binary values.
Ron Fehd the macro or (0,1) maven CDC Atlanta GA USA RJF2@cdc.gov
If you always try to be logical,
you probably won't ever have much sorrow,
or much fun.
-- Ashleigh Brilliant pot-shot #4438