BookmarkSubscribeRSS Feed
deleted_user
Not applicable
Hi guys
I've created the arrays theID&i and theDesc&i and they works ok, but in addition, seems that SAS sees the variables with such names and says:
WARNING: Apparent symbolic reference THEID not resolved.
WARNING: Apparent symbolic reference THEDESC not resolved.
Can't understand why, and how to avoid this warnings O_o

data null;
set work.logins end=eof;
call symput(compress('"theID"||put(_n_,best.))',trim(Id));
call symput(compress('"theDesc"||put(_n_,best.))',trim(Desc));
if eof then call symput('obscnt',put(_n_,best.));
run;

data null;
%do i=1 %to &obscnt;
%SingleUpdate("&theID&i", "&theDesc&i");
%end;
run;


Thanks
6 REPLIES 6
deleted_user
Not applicable
I think that the warnings are due to the fact that the macro processor while resolving the macro variables traverse from left to right. So in your case when it confronts &theID&i it sees it as (&theID)(&i), so while trying to resolve &theID it gives the warnings and resolves &i to it's numeric value. On the next pass it gets &theiD1 (say when &i resloves to 1) and correctly resloves it.

So the way to avoid the warnings will be to code in such a way that &i is resolved first and then &theID<> is resolved.
deleted_user
Not applicable
> So the way to avoid the warnings will be to code in such a way that &i is resolved first and then &theID is resolved.

I am not sure that the problem appears in &i, because &i uses later. Seems that problem appears in _n_. But I still have no idea how to avoid it O_o
darrylovia
Quartz | Level 8
Are you sure that you are getting exactly what you want? I may have missed something but your data _null_ module should have double&. That should cure your warning message.

In your example the macro processor replaces the &i and the &theID at the "same time" so SAS is looking for &i which it can find but it can't find &theID b/c it doesn't exist. With a double ampersand, SAS resolves the && to a single &. So when the macro facility sees &&theID&i, the first iteration will look like &theID1 then &theID1 gets resolved. Cynthia and others on this site have offered much more elegant explainations.

See my examples


Try this:

data _null_;
%do i=1 %to &obscnt;
%SingleUpdate("&&theID&i", "&&theDesc&i");
%end;
run;




See my example to show how the && and & resolve

data test;
input id desc $;
datalines;
1 NORTH
2 SOUTH
3 EAST
4 WEST
;
run;

%macro test_macro;

data _null_;
set test end=eof;
call symput('theID'||strip(put(_n_,best.)),strip(put(id,best.)));
call symput('theDESC'||strip(put(_n_,best.)),strip(desc));
if eof then call symput ('obscnt',strip(put(_n_,best.)));
run;

proc sql;
select *
from dictionary.macros
where name like 'THEID%' or name like 'THEDESC%' or name eq 'OBSCNT';
quit;

%put Will Generate a Warning;
%do i=1 %to &obscnt;
%put '&theID&i'=&theID&i '&theDESC&i'=&theDESC&i;
%end;
%put;
%put Will Not Generate a Warning;
%do i=1 %to &obscnt;
%put '&&theID&i'=&&theID&i '&&theDESC&i'=&&theDESC&i;
%end;


%mend test_macro;
%test_macro;

-Regards/
Darryl
LAP
Quartz | Level 8 LAP
Quartz | Level 8
This may be over simplifiying the problem but you don't need to use the single quotes around the entire name ie... '"theID"||put(_n_,best.))'. You only need the quotes around "theID".
deleted_user
Not applicable
Okay, let's use more efficient functions. Say, the test data was generated as


data test;
do i=1 to 10;
id = int(ranuni(0)*1000 + 0.5);
desc = int(ranuni(0)*20 + 0.5);
output;
end;
drop i;
run;

Then your codes


data _null_;
set test end=eof;
call symput('theID'||strip(put(_n_,best.)),strip(put(id,best.)));
call symput('theDESC'||strip(put(_n_,best.)),strip(desc));
if eof then call symput ('obscnt',strip(put(_n_,best.)));
run;
%put _user_;

Nothing wrong, but too fuzzy with quotes. How about with the new functions?

data _null_;
set test end=eof;
call symputx(catt('theID', _n_), id);
call symputx(catt('theDESC', _n_), desc);
if eof then call symputx('obscnt', _n_);
run;
%put _user_;

Same macro variables, but no more
NOTE: Numeric values have been converted to character values at the places given by: (Line):(Column).
927:54


You don't need to use ||, ", ', best, strip, trim, etc.
symputx, catt, catx, etc are efficient functions and more general
deleted_user
Not applicable
Hippo ,

Macro arrays are arcian and out dated as much as past since they became popular. The first data step is correct code for Version 8 Macro array creation, however if you are using V9 try using Call SymputX.

The warnings you are getting are coming from the use of the macro variables you are creating in the first step.

This:

%SingleUpdate("&theID&i", "&theDesc&i");


Should Be:

%SingleUpdate("&&theID&i", "&&theDesc&i");

Now beyond that tid bit Id have to see what the SingleUpDate macro code is to determine if it is even needed, the quotes are needed in the macro call, or even if the semi colon is needed.

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 6 replies
  • 6345 views
  • 0 likes
  • 3 in conversation