I may have asked this before I've been thinking about it for a long time.
Suppose I want to collect user input in the form of an array initialization. I want to use SAS to parse or expand the initialization e.g.
152 %let parm = (4*40 3*(3*7 8 9 10));
153 data _null_;
154 array parm[30];
155 retain parm &parm;
WARNING: Partial value initialization of the array parm.
156 put (parm
) (/=); 157 run;
parm1=40
parm2=40
parm3=40
parm4=40
parm5=7
parm6=7
parm7=7
parm8=8
parm9=9
parm10=10
parm11=7
parm12=7
parm13=7
parm14=8
parm15=9
parm16=10
parm17=7
parm18=7
parm19=7
parm20=8
parm21=9
parm22=10
parm23=.
parm24=.
parm25=.
parm26=.
parm27=.
parm28=.
parm29=.
parm30=.
As you can see SAS knows just what to do and give me exactly what I want. I just don't want the warning. I even works for character strings.
204 %let parm = (4*'hello kitty' 3*(3*('hello yourself')));
205 data _null_;
206 array parm[30] $32;
207 retain parm &parm;
WARNING: Partial value initialization of the array parm.
208 put (parm
) (/=); 209 run;
parm1=hello kitty
parm2=hello kitty
parm3=hello kitty
parm4=hello kitty
parm5=hello yourself
parm6=hello yourself
parm7=hello yourself
parm8=hello yourself
parm9=hello yourself
parm10=hello yourself
parm11=hello yourself
parm12=hello yourself
parm13=hello yourself
parm14=
parm15=
parm16=
parm17=
parm18=
parm19=
parm20=
parm21=
parm22=
parm23=
parm24=
parm25=
parm26=
parm27=
parm28=
parm29=
parm30=
The only way I can see to get rid of the warning it to know what the number of elements the "initialization list" is going to produce. But I ain't smart enough for that and why should I need to cause SAS knows already. I just don't want to be warned.
Perhaps another feature in SAS accepts the same "initialization list" syntax that doesn't produce the WARNING.
Perhaps a recursive macro to parse the initialization string and count the number of entries? Might not be too hard for numeric values.
An interesting challange perhaps, but I don't want to do ANYTHING that SAS already knows how to do. SAS makes programming easier right? :smileygrin:
Too bad data step does not have a dynamic array feature like proc fcmp (but even there is only for numeric array anyway).
Are there other statements or procedures that allow a similar syntax for specifying values? That could be used to help determine the number of values specified. Value labels for an AXIS statement perhaps?
Someone with REGEX skills might be able to convert the string to a series of 1's and + signs so that %EVAL() could count the number of terms.
%let parm= (4*40 3*(3*7 8 9 10));
%let parm2=(4*1+3*(3*1+1+1+1));
%let nparm=%eval(&parm2);
%put nparm=&nparm;
nparm=22
It's not pretty:
%let parm=(40*4 3*(3*7 8 9 10));
%let parm2=%sysfunc(translate(%sysfunc(prxchange(%str(s/\b[0-9]{1,}\b(?!\*)/1/),-1,&parm)),+,%str( )));
(40*1+3*(3*1+1+1+1))
s/\b[0-9]{1,}\b(?!\*)/1/
this is a fairly complex regular expression
\b[0-9]{1,}\b
find a word that is made up of 1 or more digits 0-9 (\b is like \W)
(?!\*)
lookahead, do not match a literal * (use lookahead to not add this character to %1 for replacement later)
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.