BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
chinli72
Obsidian | Level 7

Hi Everybody,

 

    Please help me to explain why in below the "%put &=u" is executed only once during the do-loop when i=5, while "put i=" is executed every iteration of the loop. The evidence is in the log below the code under line 76 and under line 79. Many thanks for the help. 

data loop;
 do i=1 to 5;
   call symput("u",put(i, 1.));
   %put &=u;
   put i=;
 end;
run;
 1          OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
 SYMBOLGEN:  Macro variable _SASWSTEMP_ resolves to /folders/myfolders/.sasstudio/.images/68d8567e-556b-4297-83b9-f0b6abc1b09d
 SYMBOLGEN:  Some characters in the above value which were subject to macro quoting have been unquoted for printing.
 SYMBOLGEN:  Macro variable GRAPHINIT resolves to  
 72         
 73         data loop;
 74          do i=1 to 5;
 75            call symput("u",put(i, 1.));
 76            %put &=u;
 SYMBOLGEN:  Macro variable U resolves to            5
 U=           5
 77            put i=;
 78          end;
 79         run;
 
 i=1
 i=2
 i=3
 i=4
 i=5
 NOTE: The data set WORK.LOOP has 1 observations and 1 variables.
 NOTE: DATA statement used (Total process time):
       real time           0.00 seconds
       cpu time            0.00 seconds
   
1 ACCEPTED SOLUTION

Accepted Solutions
SuryaKiran
Meteorite | Level 14
 SYMBOLGEN:  Macro variable U resolves to            5

 "U" will not be resolved to anything if you run the same program you provided, you will get that log if you run the same program the second time. 

 

You need to understand how SYMPUT works. You cannot reference the macro to retrieve the value in the same program in which SYMPUT creates that macro variable and assigns a value to it.

 

Problem Trying to Reference a SYMPUT-Assigned Value Before It Is Available
One of the most common problems in using SYMPUT is trying to reference a macro variable value assigned by SYMPUT before that variable is created. The failure generally occurs because the statement referencing the macro variable compiles before execution of the CALL SYMPUT statement that assigns the variable's value. The most important fact to remember in using SYMPUT is that it assigns the value of the macro variable during program execution. Macro variable references resolve during the compilation of a step, a global statement used outside a step, or an SCL program. As a result:
- You cannot use a macro variable reference to retrieve the value of a macro variable in the same program (or step) in which SYMPUT creates that macro variable and assigns it a value.
- You must specify a step boundary statement to force the DATA step to execute before referencing a value in a global statement following the program (for example, a TITLE statement). The boundary could be a RUN statement or another DATA or PROC statement.

 

For example:
data x;
x='December';
call symput('var',x);
proc print;
title "Report for &var";
run;

 

 

Source: http://support.sas.com/documentation/cdl/en/mcrolref/62978/HTML/default/viewer.htm#p09y28i2d1kn8qn1p...

 

Thanks,
Suryakiran

View solution in original post

14 REPLIES 14
VDD
Ammonite | Level 13 VDD
Ammonite | Level 13
data loop / debug;
 do i=1 to 5;
   call symput("u",put(i, 1.));
   %put &=u;
   put i=;
   output;
 end;
run;

have you tried the debugger?

the process works as written.

 

try this:

data loop ;
 do i=1 to 5;
   call symput("u",put(i, 1.));
   put i=;
	%put &=u;
 end;
run;

 

chinli72
Obsidian | Level 7
Thank you for the Debug suggestion. Unfortunately, when I tried it using SAS University Edition,it say the debugger can not be initialized. I think it is not available.
RW9
Diamond | Level 26 RW9
Diamond | Level 26

You need to understand that Macro and Datastep are two very different things.  This has been explained many times on this forum, and in the documentation:

http://support.sas.com/documentation/cdl/en/mcrolref/62978/HTML/default/viewer.htm#n189qvy83pmkt6n1b...

 

Do not mix macro an datastep up, they are two separate systems.

 

If you can explain what you are trying to do, we can show a better way.  However for the moment, you create the macro variables in the datastep execution, then after the execution, you can then use those macro variables:

data loop;
 do i=1 to 5;
   call symputx(cats("u",put(i, 1.)),put(i,best.));
   put i=;
 end;
run;
%put &u1.;
%put &u2.;

Otherwise the only variable printed will be the last iteration, after the datastep has finished executing.

 

Oh, and you have a typo, %put &=u;  should read, %put &u.;

chinli72
Obsidian | Level 7

Hi RW9,

 

    Thank you for your explanations and code example. While I was coding the macro code below and thought if I could do a similar thing in DATA step. Based on you example code, I can't macro "%put" the similar way as I use data step  "put". It is not that obvious for a SAS beginner.

option nomlogic nosymbolgen;
%macro mloop;
   %do i=1 %to 5;
      %let m=&i;
      %put &=m;
   %end;
%mend;
%mloop;
FreelanceReinh
Jade | Level 19

To create another example demonstrating the timing, you could write this %PUT statement

%put Macro: %sysfunc(time(), time8.); /* just to demonstrate the timing */

into a DATA _NULL_ step, after the statements below

call sleep(5,1); 
t=time();
put 'DATA step: ' t time8.;

(but before the RUN statement).

 

Then compare the (misleading) order of the PUT and %PUT statements to the results in the log.

 


@chinli72 wrote:

I can't macro "%put" the similar way as I use data step  "put". It is not that obvious for a SAS beginner.

Indeed. And it shows that it's a good idea "for a SAS beginner" not to learn DATA step programming and SAS macro programming in parallel, but to become familiar with the DATA step first. This will save you a lot of headaches.

 




chinli72
Obsidian | Level 7

Hi FreelanceReinhard,

 

    I've tested your code and found that "%put Macro:.." finishes before t=time();. Indeed, macro gets run first. Thank you so much for the brilliant demonstration.

 

Chin

 

RW9
Diamond | Level 26 RW9
Diamond | Level 26

Yes, that code is all running in the macro pre-processor.  In fact datastep is not used at all an nothing is compiled.  The same things from a datastep would be:

data want;
  do i=1 to 5;
    output;
  end;
run;

proc print data=want;
run;

I would advise that you learn Base SAS (also known as Datastep) first, and fully.  All code can be done in that, and all macro is there to do is generate some text which can be Base SAS code.  Do not fall into the usual issue of trying to code things in Macro, it is not for that, it is for a specific function nothing more.

FreelanceReinh
Jade | Level 19

Hi @chinli72,

 

As a macro statement, %PUT is executed before the DATA step (in this case even before the compilation of the DATA step has finished). If you run this code in a new SAS session (where macro variable U has not been defined yet), you will therefore get a warning message

WARNING: Apparent symbolic reference U not resolved.

So, writing a %PUT statement (or, e.g., a %LET statement) in the middle of a DATA step is misleading. It suggests that it will be executed between the DATA step statements (e.g. in your case return the value assigned by the CALL SYMPUT routine preceding the %PUT statement), but this is not the case.

chinli72
Obsidian | Level 7

Macro statement is run 1st even though it appears that data step is. I do recall that I read in a book by Delwiche and Slaughter which talked about macro statements are processed by macro processor first before SAS processor. That didn't mean much till I see your explanation. Thank you so much.

SuryaKiran
Meteorite | Level 14
 SYMBOLGEN:  Macro variable U resolves to            5

 "U" will not be resolved to anything if you run the same program you provided, you will get that log if you run the same program the second time. 

 

You need to understand how SYMPUT works. You cannot reference the macro to retrieve the value in the same program in which SYMPUT creates that macro variable and assigns a value to it.

 

Problem Trying to Reference a SYMPUT-Assigned Value Before It Is Available
One of the most common problems in using SYMPUT is trying to reference a macro variable value assigned by SYMPUT before that variable is created. The failure generally occurs because the statement referencing the macro variable compiles before execution of the CALL SYMPUT statement that assigns the variable's value. The most important fact to remember in using SYMPUT is that it assigns the value of the macro variable during program execution. Macro variable references resolve during the compilation of a step, a global statement used outside a step, or an SCL program. As a result:
- You cannot use a macro variable reference to retrieve the value of a macro variable in the same program (or step) in which SYMPUT creates that macro variable and assigns it a value.
- You must specify a step boundary statement to force the DATA step to execute before referencing a value in a global statement following the program (for example, a TITLE statement). The boundary could be a RUN statement or another DATA or PROC statement.

 

For example:
data x;
x='December';
call symput('var',x);
proc print;
title "Report for &var";
run;

 

 

Source: http://support.sas.com/documentation/cdl/en/mcrolref/62978/HTML/default/viewer.htm#p09y28i2d1kn8qn1p...

 

Thanks,
Suryakiran
chinli72
Obsidian | Level 7

Thank you for quoting the original source of the explanation of the phenomenon. You are basically telling me that I can't use Call SYMPUT and %PUT in the same data step because the macro variable is yet generated by Call SYMPUT when %put is using it. Boy that is just not so obvious. Thanks again.

Ksharp
Super User

%put is macro statement not data step statement, and %put is global .

The following code could help you to understand WHY .

 

data loop;
 do i=1 to 5;
   call symput("u",put(i, 1. -l));
   put i=;
 end;
run;


%put WARNING: &u;
chinli72
Obsidian | Level 7

Hi Ksharp,

 

     I've tried your code and verified that u is indeed a global macro variable. Thank you so much for the help.

 

-Chin

Ksharp
Super User

%put is macro statement not data step statement, and %put is global .

The following code could help you to understand WHY .

 

data loop;
 do i=1 to 5;
   call symput("u",put(i, 1. -l));
   put i=;
 end;
run;


%put WARNING: &u;

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
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
  • 14 replies
  • 3687 views
  • 5 likes
  • 6 in conversation