Date: Mon, 24 Nov 2003 16:26:24 +0100
Reply-To: "Groeneveld, Jim" <jim.groeneveld@VITATRON.COM>
Sender: "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From: "Groeneveld, Jim" <jim.groeneveld@VITATRON.COM>
Subject: Re: Macros that return values in specified macro variables
Content-Type: text/plain; charset="iso-8859-1"
Hi Richard,
Another alternative with macros like you present, NOT containing any SAS code, only macro code, is to return the value of RC as the result of the macro call. Thus in your macro code at the end just specify:
&RC /* without semicolon */
and remove the RC argument from the parameter list;
and call your macro by:
%LET RC = %attrc (data=foo.bar, lib=libname, mem=memname);
Se a.o. http://listserv.uga.edu/cgi-bin/wa?A2=ind0310C&L=sas-l&P=R13877
Regards - Jim.
--
. . . . . . . . . . . . . . . .
Jim Groeneveld, MSc.
Biostatistician
Science Team
Vitatron B.V.
Meander 1051
6825 MJ Arnhem
Tel: +31/0 26 376 7365
Fax: +31/0 26 376 7305
Jim.Groeneveld@Vitatron.com
www.vitatron.com
My computer has the solutions, I have the problems.
[common disclaimer]
-----Original Message-----
From: Richard A. DeVenezia [mailto:radevenz@IX.NETCOM.COM]
Sent: Monday, November 24, 2003 15:31
To: SAS-L@LISTSERV.UGA.EDU
Subject: Macros that return values in specified macro variables
Sometimes a macro has to return a status value to the caller so the caller
can make a decision. Typically the status value is some sort of error code,
other times, the value is one of several that get set by the macro.
Consider this macro
%macro attrc (data=, lib=, mem=, rc=);
%local dsid;
%let dsid = %sysfunc (open (&data));
%if &dsid %then %do;
%let &lib = %sysfunc (attrc(&dsid,LIB));
%let &mem = %sysfunc (attrc(&dsid,MEM));
%let &rc = 0;
%end;
%else %do;
%let &rc = -1;
%end;
%mend;
options nosource;
%let libname=;
%let memname=;
%let rc=;
%let xrc=;
%attrc (data=sashelp.class, lib=libname, mem=memname, rc=rc);
%put libname=&libname;
%put memname=&memname;
%put rc=&rc;
%attrc (data=foo.bar, lib=libname, mem=memname, rc=rc);
%put libname=&libname;
%put memname=&memname;
%put rc=&rc;
%attrc (data=sashelp.class, lib=libname, mem=memname, rc=xrc);
%put libname=&libname;
%put memname=&memname;
%put xrc=&xrc;
%attrc (data=foo.bar, lib=libname, mem=memname, rc=xrc);
%put libname=&libname;
%put memname=&memname;
%put xrc=&xrc;
The invocations have the log showing
libname=SASHELP
memname=CLASS
rc=
libname=SASHELP
memname=CLASS
rc=
libname=SASHELP
memname=CLASS
xrc=0
libname=SASHELP
memname=CLASS
xrc=-1
One first blush I would want to say
%if &rc eq 0 %then <ok to proceed with libname and memname>
So, why did the first two invocations show rc = blank ?
Because the macro variable specified to contain the return value is also the
name of a macro variable local in scope to the macro invoked.
Thus I posit:
What is a good strategy to prevent variable name collision in macros that
are supposed to set macro variables in scope above themselves ?
Worst case I would want the macro called to generate an ERROR message to the
log if it is request to place a value in a macro variable that will be local
when the macro is running.
Is there a programmatic way to determine which macro variables are currently
defined at local scope (without going to SASHELP.VMACRO)?
Perhaps something like
%if %isLocal ( &rc ) %then %do;
%put ERROR: &rc can not be used to return a value;
%return;
%end;
...
%let &rc = < some return code value >;
or
%if &rc %in ( &_LOCALS_ ) %then %do;
%put ERROR: &rc can not be used to return a value;
%return;
%end;
where macro variable _LOCALS_ is a reserved automatic macro variable listing
all the macro variables having local scope. (Probably not feasible;
consider a macro utilizing a macro 'array' having thousands of elements)
--
Richard A. DeVenezia