BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
ifb10
Obsidian | Level 7
Hello,
I have been trying to update the macro variable egg with each iteration of my loop using call symputx and %sysevalf. It did not work, instead the macro variable Eggs remained constant.  I could possibly update the macro variable with a %let statement ( %let Eggs = %eval(&Eggs. - 1);). Yet I was wondering, why it did not work with the symputx call. 
 
%macro Hatchery (Eggs = 6);
 
%if &Eggs. > 0 %then %do;
data crap.hatchery;
/* %do %until (&Eggs. < 1); */
%do index= 1 %to 3;
%put NOTE: &Eggs.;
Larva +1;
call symputx("Eggs", %sysevalf(&Eggs. - 1));
call symputx("Larva", Larva);
%end;
run;
%end;
 
%mend Hatchery;
1 ACCEPTED SOLUTION

Accepted Solutions
5 REPLIES 5
BrunoMueller
SAS Super FREQ

I suggest to run your macro using this statement before calling the macro

options mprint mlogic;

Some basic rules on macro processing:

  • The macro facility produces text that the compiler will process later
  • Macro statements and functions are executed before the DATA step compiles/executes 

You are mixing DATA step logic with macro processing logic. Just use DATA step programming for your loop.

Are you looking for something like this?


%let eggs = 4;

data hatchery;
  eggs = &eggs;

  do until (Eggs < 1);
    putlog "NOTE: " eggs=;
    eggs = eggs - 1;
    Larva +1;
    output;
  end;
run;
Kurt_Bremser
Super User

Since you never assign a new value to the macro variable eggs, it will stay at 6 (or whatever value you use in the macro call) throughout, and the result of the %SYSEVALF will always be 5.

Tom
Super User Tom
Super User

Since the only place you are changing the value of EGGS is with data step code the value of EGGS will not change until after the data step start running. The data step will not start running until after it has been fully defined.  

 

Once the macro %DO loop is finished  running your data step is going to look like:

data crap.hatchery;
Larva +1;
call symputx("Eggs", 5);
call symputx("Larva", Larva);
Larva +1;
call symputx("Eggs", 5);
call symputx("Larva", Larva);
Larva +1;
call symputx("Eggs", 5);
call symputx("Larva", Larva);
run;

I do not see why you need any macro logic here at all.

%macro Hatchery (Eggs = 6);
data crap.hatchery;
  do eggs=&eggs to 0 by -1;
    Larva +1;
    output;
 end;
run;
%mend Hatchery;
ifb10
Obsidian | Level 7

Thank you @Tom for the detailed answer. 

 

The main purpose was to understand the macro logic a bit better.  Especially the macro variable definitions in a local environment using proc sql, call symputx and %let statement. 

In this regard your answer was perfectly explaining why call symputx can not work under this setting. 

Yet I was wondering, why does the same logic not apply to the %let statement? I tried following code which did the job: 

 

 

 

%macro Hatchery (Eggs = 6);

data crap.hatchery;
%do index= 1 %to 3;
%put NOTE: &Eggs.;
Larva +1;
%let Eggs = %eval(&Eggs. - 1);
call symputx("Larva", Larva);
%end;
run;
%mend Hatchery;

%Hatchery

 

 

Is it because the %let statement is directly processed in the macro processor and the symbol table is immediately updated after each iteration? I guess in contrast to that I get similar results to call symputx with proc sql select into clause as you described. My guess is that Macro processor is not triggered by either call symputx nor select into (proc sql) which are instead resolved as you described only after compilation. 

data crap.hatchery;
Larva +1;
call symputx("Eggs", 5);
call symputx("Larva", Larva);
Larva +1;
call symputx("Eggs", 5);
call symputx("Larva", Larva);
Larva +1;
call symputx("Eggs", 5);
call symputx("Larva", Larva);
run;

 

Thanks again, now I have only to find out how I can mark your answer as solution as well. 

 

Tom
Super User Tom
Super User

If you turn on SYMBOLGEN option (and perhaps MLOGIC) option you will see more messages in the log showing what the macro processor is doing.  (I do not recommend turning those on except for debugging the macro code because your log will become unreadable.)

 

Just step through it yourself and see what it is doing.

 

data crap.hatchery;
%do index= 1 %to 3;
%put NOTE: &Eggs.;
Larva +1;
%let Eggs = %eval(&Eggs. - 1);
call symputx("Larva", Larva);
%end;
run;

It generates a DATA statement.

Then the %DO runs.  So when INDEX=1 it:

 

  1. writes a note to the log. 
  2. generates a SUM statement. 
  3. increments the macro variable EGGS. 
  4. generates a CALL SYMPUTX() statement. 

Then it does the same thing two more times.

 

Finally it generates the RUN statement so the data step can start being compiled and run.

The resulting data step is kind of silly looking and does not seem to have any purpose.

data crap.hatchery;
Larva +1;
call symputx("Larva", Larva);
Larva +1;
call symputx("Larva", Larva);
Larva +1;
call symputx("Larva", Larva);
run;

So all it does is create a dataset with one observation and one variable named LARVA with a value of 3.  It also sets the macro variable named LARVA to the digit 3.

 

SAS Innovate 2025: Call for Content

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!

Submit your idea!

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
  • 5 replies
  • 953 views
  • 4 likes
  • 4 in conversation