Date: Mon, 21 Dec 2009 01:03:24 -0500
Reply-To: Scott Bass <sas_l_739@YAHOO.COM.AU>
Sender: "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
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