Hi,
I have a "loop" macro as follows:
/*---------------------------------------------------------------------
* PROGRAM: loop
* DESCRIPTION: A "wrapper" macro to execute code over a list of items
* SAS VERSION: SAS 8.2
* DATE: 24 Apr 2006
* AUTHOR: Scott Bass
*
* MODIFICATIONS:
* =============
* Date UID Description
* ----------- --- ----------------------------------------------------
* 24 Apr 2006 SLB Initial revision
* 17 Jul 2006 SLB Added DLM parameter
---------------------------------------------------------------------*/
%macro loop
/*---------------------------------------------------------------------
Invoke the nested macro "%code" over a list of space separated
list of items.
---------------------------------------------------------------------*/
(__LIST__ /* Space or character separated list of items (REQ) */
,DLM=%str( ) /* Delimiter character (REQ). Default is a space. */
,MNAME=code /* Macro name (Optional). Default is "%code" */
);
/*---------------------------------------------------------------------
Usage:
%macro code;
%put &word;
%mend;
%loop(Hello World);
%let str = Hello,World;
%loop(%bquote(&str),dlm=%bquote(,));
%macro mymacro;
proc print data=&word;
run;
%mend;
proc datasets kill nowarn nolist;
quit;
data one;x=1;run; data two;y=2;run;
proc sql noprint;
select memname into :list separated by '|'
from dictionary.tables
where libname = "WORK" and memtype = "DATA"
;
quit;
%loop(&list,dlm=|,mname=mymacro);
proc sql noprint;
select trim(value) into :list separated by '^'
from your_dataset
;
quit;
%loop(&list,dlm=^);
-----------------------------------------------------------------------
Notes:
The nested macro "%code" must be created at run time before calling
this macro.
Use the macro variable "&word" within your %code macro for each token
(word) in the input list.
If your input list has embedded blanks, specify a different dlm value.
---------------------------------------------------------------------*/
%local macro parmerr iter;
/*
%* check input parameters ;
%let macro = &sysmacroname;
%parmv(__LIST__, _req=1,_words=1,_case=N)
%if (&parmerr) %then %goto quit;
*/
%* make sure the iterator is unique ;
%* if %code resets the iterator problems occur ;
%let iter = _%substr(&sysprocessid,1,6)_;
%local &iter;
%let &iter = 1;
%let word = %scan(%superq(__list__),&&&iter,%str(&dlm));
%do %while (%superq(word) ne %str());
%&mname /* do not indent macro call */
%let &iter = %eval(&&&iter+1);
%let word = %scan(%superq(__list__),&&&iter,%str(&dlm));
%end;
%quit:
%mend;
Now, compare the invocation of %loop in the following scenarios:
options mlogic symbolgen;
%macro test;
%put *** &word ***;
%mend;
%loop(Hello World,mname=test);
%macro test(parm=);
%put *** &word ***;
%mend;
%loop(Hello World,mname=test);
%macro test(parm1,parm2,parm3);
%put *** &word ***;
%mend;
%loop(Hello World,mname=test);
The first version works, the 2nd and 3rd versions don't. Any ideas why
macro parameters (even if they aren't used) cause the outer %loop macro
variable parsing logic to fail? Could this be a bug in macro?
Thanks,
Scott
|
|
0
|
|
|
|
Reply
|
sas_l_739 (82)
|
12/21/2009 6:03:24 AM |
|
Summary: How does the macro facility know when macro invocation
is finished?
#iw-value=1
Scott,
The answer is no, it is not a bug. The question you should ask
is:
How does the macro facility know when macro invocation is finished?
Answer:
1) When no parameters, when name is finished invoke named macro.
2) When parameters (possibly empty), when something indicates
the parameter list has been passed.
Your last two calls should have been
%loop(Hello World,mname=test())
since the user, not the LOOP author, should know how his macro is to be
called.
Data_null_'s work around %UNQUOTE works because the closing parenthis
of the %UNQUOTE indates the argument is finished and thus the invocation
of TEST is finished. He could just as well have used %UPCASE or for
more mystery %FIX where the macro is
%macro fix ( dummy ) ; %mend ;
Incidentally your indirection with
%* make sure the iterator is unique ;
%* if %code resets the iterator problems occur ;
%let iter = _%substr(&sysprocessid,1,6)_;
%local &iter;
doesn't work. Consider
%macro break ;
%let iter = nogood ;
%mend break ;
%loop (Hello World, mname = break)
There is no good fix for the problem since macros can see variables
in the outer environment. I prefer an announced prefix that the user
should avoid. For a fixed prefix I commonly use __. Otherwise,
make it a parameter say, PREF=XYZ, and then the reference is
&&&PREF._vname where VNAME is your choice.
Further more your %LOCAL should precede the assignment as shown
by having an outer variable ITER.
%global iter ;
%macro oops ;
%let iter = nogood ;
%local iter ;
%put iter = >>>&iter<<< ;
%mend oops ;
%oops
Ian Whitlock
Date: Mon, 21 Dec 2009 01:03:24 -0500
From: Scott Bass <sas_l_739@YAHOO.COM.AU>
Subject: Is this a macro bug???
Hi,
I have a "loop" macro as follows:
/*---------------------------------------------------------------------
* PROGRAM: loop
* DESCRIPTION: A "wrapper" macro to execute code over a list of items
* SAS VERSION: SAS 8.2
* DATE: 24 Apr 2006
* AUTHOR: Scott Bass
*
* MODIFICATIONS:
* =============
* Date UID Description
* ----------- --- ----------------------------------------------------
* 24 Apr 2006 SLB Initial revision
* 17 Jul 2006 SLB Added DLM parameter
---------------------------------------------------------------------*/
%macro loop
/*---------------------------------------------------------------------
Invoke the nested macro "%code" over a list of space separated
list of items.
---------------------------------------------------------------------*/
(__LIST__ /* Space or character separated list of items (REQ) */
,DLM=%str( ) /* Delimiter character (REQ). Default is a space. */
,MNAME=code /* Macro name (Optional). Default is "%code" */
);
/*---------------------------------------------------------------------
Usage:
%macro code;
%put &word;
%mend;
%loop(Hello World);
%let str = Hello,World;
%loop(%bquote(&str),dlm=%bquote(,));
%macro mymacro;
proc print data=&word;
run;
%mend;
proc datasets kill nowarn nolist;
quit;
data one;x=1;run; data two;y=2;run;
proc sql noprint;
select memname into :list separated by '|'
from dictionary.tables
where libname = "WORK" and memtype = "DATA"
;
quit;
%loop(&list,dlm=|,mname=mymacro);
proc sql noprint;
select trim(value) into :list separated by '^'
from your_dataset
;
quit;
%loop(&list,dlm=^);
-----------------------------------------------------------------------
Notes:
The nested macro "%code" must be created at run time before calling
this macro.
Use the macro variable "&word" within your %code macro for each token
(word) in the input list.
If your input list has embedded blanks, specify a different dlm value.
---------------------------------------------------------------------*/
%local macro parmerr iter;
/*
%* check input parameters ;
%let macro = &sysmacroname;
%parmv(__LIST__, _req=1,_words=1,_case=N)
%if (&parmerr) %then %goto quit;
*/
%* make sure the iterator is unique ;
%* if %code resets the iterator problems occur ;
%let iter = _%substr(&sysprocessid,1,6)_;
%local &iter;
%let &iter = 1;
%let word = %scan(%superq(__list__),&&&iter,%str(&dlm));
%do %while (%superq(word) ne %str());
%&mname /* do not indent macro call */
%let &iter = %eval(&&&iter+1);
%let word = %scan(%superq(__list__),&&&iter,%str(&dlm));
%end;
%quit:
%mend;
Now, compare the invocation of %loop in the following scenarios:
options mlogic symbolgen;
%macro test;
%put *** &word ***;
%mend;
%loop(Hello World,mname=test);
%macro test(parm=);
%put *** &word ***;
%mend;
%loop(Hello World,mname=test);
%macro test(parm1,parm2,parm3);
%put *** &word ***;
%mend;
%loop(Hello World,mname=test);
The first version works, the 2nd and 3rd versions don't. Any ideas why
macro parameters (even if they aren't used) cause the outer %loop macro
variable parsing logic to fail? Could this be a bug in macro?
Thanks,
Scott
|
|
0
|
|
|
|
Reply
|
iw1sas
|
12/23/2009 6:47:12 PM
|
|
|
1 Replies
206 Views
(page loaded in 0.051 seconds)
Similiar Articles: Is this a macro bug??? - comp.soft-sys.sasHi, I have a "loop" macro as follows: /*----- * PROGRAM: loop * DESCRIPTIO... ... Hi, I have a ... Async IO bug - comp.databases.oracle.serverIs this a macro bug??? - comp.soft-sys.sas Async IO bug - comp.databases.oracle.server Is this a macro bug??? - comp.soft-sys.sas Async IO bug - comp.databases.oracle ... macros for path,names, concat, and output export - comp.soft-sys ...Is this a macro bug??? - comp.soft-sys.sas macros for path,names, concat, and output export - comp.soft-sys ... > > TIA, > > Lance You could do that sort of thing with ... Where clause usage in %if in macro - comp.soft-sys.sasIs this a macro bug??? - comp.soft-sys.sas Where clause usage in %if in macro - comp.soft-sys.sas Is this a macro bug??? - comp.soft-sys.sas Use the macro variable ... Pass a variable as a macro parameter. - comp.soft-sys.sas ...Is this a macro bug??? - comp.soft-sys.sas Use the macro variable "&word" within your %code macro for each token ... Pass a variable as a macro parameter. - comp.soft-sys ... Where used macro? - comp.cad.solidworksIs this a macro bug??? - comp.soft-sys.sas Use the macro variable "&word" within your %code macro for each token (word) in the input list. If your input list has embedded ... What is the option in Macro to display ERROR message if macro ...Where clause usage in %if in macro - comp.soft-sys.sas Is this a macro bug??? - comp.soft-sys.sas Use the macro variable "&word ... What is the option in Macro to display ... using a word as delimiter in scan - comp.soft-sys.sasBut you could consider making your own scanwd function (or even macro) based on Ya ... Is this a macro bug??? - comp.soft-sys.sas... Space or character separated list of ... Why won't SAS fix PROC EXPORT - comp.soft-sys.sasIs this a macro bug??? - comp.soft-sys.sas... str),dlm=%bquote(,)); %macro mymacro; proc ... version works, the 2nd and 3rd versions don't. Any ideas why ... as well have ... Save as DWG macro - comp.cad.solidworksWe have been using a macro to save a drawing as a PDF that was last enhanced by ... the DWG save not return those same errors? > > =A0 WT WT, It may actually be a bug. Bug Macros by Bob FrankPanasonic FZ30 with Raynox DCR-250 Galleries: Flies : Damselflies: Hoverflies: Plant Bugs. Ants: Beetles & Lady Bugs: Hoppers: Various Insects: Foliage: Assassin Bugs Flickr: Macro Bugs - Welcome to Flickr - Photo Sharingby MentalBloc16. by nikkorglass. by CWAbramo. by AnnvW. by the.flea. by mwjw. by mwjw. by washingto... by moshek70. by Emery O. by Thomas Kent. by Josh_G » 7/18/2012 1:31:46 AM
|