Macro variable resolution order
Macro variable resolution order
(OP)
Hi.
Can someone please explain why macro variable email is not resolving?
Here is some code the generates the WARNING.
Here is the resultant log
1 *** PROBLEM 1;
2
3 %macro report1;
4 %let email = 1;
5 %inc dev(program2);
6 %mend report1;
7
8 %macro report2;
9 %let email = 2;
10 %inc dev(program2);
11 %mend report2;
12
13 data test;
14 run = 'YES';
15 run;
NOTE: The data set WORK.TEST has 1 observations and 1 variables.
NOTE: The DATA statement used 0.02 CPU seconds and 10536K.
16 data _null_;
17 set test;
18 call execute('%report1');
19 call execute('%report2');
20 run;
MPRINT(REPORT1): %inc dev(program2);
MPRINT(REPORT2): %inc dev(program2);
NOTE: There were 1 observations read from the data set WORK.TEST.
NOTE: The DATA statement used 0.01 CPU seconds and 10556K.
NOTE: CALL EXECUTE generated line.
1 + %inc dev(program2);
NOTE: %INCLUDE (level 1) file DEV(program2) is file
ACTUXK2.SAS.DEVLIB(PROGRAM2).
21 +*** PROGRAM2;
22 +%macro email020;
23 + %if &email = 1 %then %do;
24 + %put THIS RESOLVED AT 1;
25 + %end;
26 + %else %if &email = 2 %then %do;
27 + %put THIS RESOVLED AT 2;
28 + %end;
29 + %put _user_;
30 +%mend email020;
31 +%email020;
WARNING: Apparent symbolic reference EMAIL not resolved.
ERROR: A character operand was found in the %EVAL function or %IF condition
where a numeric operand is required. The condition was: &email = 1
ERROR: The macro EMAIL020 will stop executing.
NOTE: %INCLUDE (level 1) ending.
2 + %inc dev(program2);
NOTE: %INCLUDE (level 1) file DEV(program2) is file
ACTUXK2.SAS.DEVLIB(PROGRAM2).
32 +*** PROGRAM2;
33 +%macro email020;
34 + %if &email = 1 %then %do;
35 + %put THIS RESOLVED AT 1;
36 + %end;
37 + %else %if &email = 2 %then %do;
38 + %put THIS RESOVLED AT 2;
39 + %end;
40 + %put _user_;
41 +%mend email020;
42 +%email020;
WARNING: Apparent symbolic reference EMAIL not resolved.
ERROR: A character operand was found in the %EVAL function or %IF condition
where a numeric operand is required. The condition was: &email = 1
ERROR: The macro EMAIL020 will stop executing.
NOTE: %INCLUDE (level 1) ending.
I have no doubt I am missing something obvious.
Kind Regards,
Asender...
Can someone please explain why macro variable email is not resolving?
Here is some code the generates the WARNING.
CODE
*** Program 1 ***;
%macro report1;
%let email = 1;
%inc dev(program2);
%mend report1;
%macro report2;
%let email = 2;
%inc dev(program2);
%mend report2;
data test;
run = 'YES';
run;
data _null_;
set test;
call execute('%report1');
call execute('%report2');
run;
*** Program 2 - This code is stored elsewhere***;
%macro email020;
%if &email = 1 %then %do;
%put THIS RESOLVED AT 1;
%end;
%else %if &email = 2 %then %do;
%put THIS RESOVLED AT 2;
%end;
%put _user_;
%mend email020;
%email020;
%macro report1;
%let email = 1;
%inc dev(program2);
%mend report1;
%macro report2;
%let email = 2;
%inc dev(program2);
%mend report2;
data test;
run = 'YES';
run;
data _null_;
set test;
call execute('%report1');
call execute('%report2');
run;
*** Program 2 - This code is stored elsewhere***;
%macro email020;
%if &email = 1 %then %do;
%put THIS RESOLVED AT 1;
%end;
%else %if &email = 2 %then %do;
%put THIS RESOVLED AT 2;
%end;
%put _user_;
%mend email020;
%email020;
Here is the resultant log
CODE
1 *** PROBLEM 1;
2
3 %macro report1;
4 %let email = 1;
5 %inc dev(program2);
6 %mend report1;
7
8 %macro report2;
9 %let email = 2;
10 %inc dev(program2);
11 %mend report2;
12
13 data test;
14 run = 'YES';
15 run;
NOTE: The data set WORK.TEST has 1 observations and 1 variables.
NOTE: The DATA statement used 0.02 CPU seconds and 10536K.
16 data _null_;
17 set test;
18 call execute('%report1');
19 call execute('%report2');
20 run;
MPRINT(REPORT1): %inc dev(program2);
MPRINT(REPORT2): %inc dev(program2);
NOTE: There were 1 observations read from the data set WORK.TEST.
NOTE: The DATA statement used 0.01 CPU seconds and 10556K.
NOTE: CALL EXECUTE generated line.
1 + %inc dev(program2);
NOTE: %INCLUDE (level 1) file DEV(program2) is file
ACTUXK2.SAS.DEVLIB(PROGRAM2).
21 +*** PROGRAM2;
22 +%macro email020;
23 + %if &email = 1 %then %do;
24 + %put THIS RESOLVED AT 1;
25 + %end;
26 + %else %if &email = 2 %then %do;
27 + %put THIS RESOVLED AT 2;
28 + %end;
29 + %put _user_;
30 +%mend email020;
31 +%email020;
WARNING: Apparent symbolic reference EMAIL not resolved.
ERROR: A character operand was found in the %EVAL function or %IF condition
where a numeric operand is required. The condition was: &email = 1
ERROR: The macro EMAIL020 will stop executing.
NOTE: %INCLUDE (level 1) ending.
2 + %inc dev(program2);
NOTE: %INCLUDE (level 1) file DEV(program2) is file
ACTUXK2.SAS.DEVLIB(PROGRAM2).
32 +*** PROGRAM2;
33 +%macro email020;
34 + %if &email = 1 %then %do;
35 + %put THIS RESOLVED AT 1;
36 + %end;
37 + %else %if &email = 2 %then %do;
38 + %put THIS RESOVLED AT 2;
39 + %end;
40 + %put _user_;
41 +%mend email020;
42 +%email020;
WARNING: Apparent symbolic reference EMAIL not resolved.
ERROR: A character operand was found in the %EVAL function or %IF condition
where a numeric operand is required. The condition was: &email = 1
ERROR: The macro EMAIL020 will stop executing.
NOTE: %INCLUDE (level 1) ending.
I have no doubt I am missing something obvious.
Kind Regards,
Asender...
RE: Macro variable resolution order
The problem here is the SCOPE of the macro variable. Macro variables by default are local in scope, they will exist within the current macro, but not outside it.
Insert this line:-
CODE
I'd recommend reading the doco on scope of Macro variables here:-
http
It's useful to know how the scoping works now that you've hit this problem once.
Lastly, for anyone else trying this, you might need to change
CODE
CODE
Chris
Business Analyst, Code Monkey, Data Wrangler.
SAS Guru.
RE: Macro variable resolution order
Thanks very much for replying.
I must confess that I have already considered and dismissed the global declaration solution.
True, the code now runs with no compilation error, but if you examine the new log you will see that the macro variable email has the same value ('2' - the last designated value) in both macro calls. This is no good.
I apologise, I should have made this clear at the start.
This is obviously a scoping issue, but as I understand it all macro variables located in a local table should be available to any macro nested within it. Do I have this correct?
I have come to the conclusion that the %inc is part of the issue. But I can't find anything definitive.
Kind Regards,
Asender...
RE: Macro variable resolution order
Sorry for posting again so soon.
I think I understand what is going on.
Even though the macro (email020) is being called from within another macro (Report1 or Report2), code within the %inc is being resolved in open code.
Try adding this %let to (program2):
CODE
%let test = TEST;
%macro email020;
%if &email = 1 %then %do;
%put THIS RESOLVED AT 1;
%end;
%else %if &email = 2 %then %do;
%put THIS RESOVLED AT 2;
%end;
%put _user_;
%mend email020;
%email020;
On checking the log you will now see that macro variable TEST is declared as GLOBAL. Indicating that the macro EMAIL020 is not being called as a nested macro. Therefore, the macro variables EMAIL which are held at a local level within Report1 and Report2 are not available to EMAIL020.
Phew, what do you think?
Kind Regards,
Asender...