SAS V9.1.3 - Ошибка при объединении% INC и CALL EXECUTE - PullRequest
2 голосов
/ 03 марта 2010

Я получаю ошибку разрешения с некоторым кодом SAS v9.1.3.

Вот некоторый код, который я хочу сохранить в файле .txt (он называется problem2.txt) и перенести в SAS с% INC

.
%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; 

Тогда это основной код:

filename problem2 'C:\Documents and Settings\Mark\My Documents\problem2.txt';

%macro report1;                            
  %let email = 1;
  %inc problem2;
%mend report1;                             

%macro report2 (inc);                            
  %let email = 2;                          
  %inc problem2;
%mend report2;                             

data test;                                 
  run = 'YES';                             
run;                                       

data _null_;                               
  set test; 
  call execute("%report1");  
  call execute("%report2");  
run;

Журнал показывает:

NOTE: CALL EXECUTE generated line.
1   +  %inc problem2;
MLOGIC(EMAIL020):  Beginning execution.

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.

MLOGIC(EMAIL020):  Ending execution.

Итак, вопрос в том, почему CALL EXECUTE генерирует% inc problem2, а не% report1, в результате чего SAS пропускает назначение и что я могу с этим сделать?

Ответы [ 2 ]

2 голосов
/ 04 марта 2010

Кажется, это проблема области видимости макроса. Попробуйте:

%macro report1;   
  %global email; 
  %let email = 1;
  %inc problem2;
%mend report1;                             

%macro report2;            
%global email; 
  %let email = 2;                          
  %inc problem2;
%mend report2;                             

Однако я думаю, что было бы лучше передать email в качестве параметра %email020, а не использовать глобальные макропеременные. Кроме того, я бы избегал использования определений вложенных макросов.

Чтобы получить больше данных в области макропеременных, вы можете запросить представление dictionary.macros во время выполнения макроса. Вы можете получить описание dictionary.macros с помощью

proc sql;
    describe table dictionary.macros;
quit;
1 голос
/ 12 марта 2010

%include - это не вызов макроса, а своего рода директива компилятора для включения кода из внешнего файла. Когда макрос %report1 компилируется, макропеременная email отсутствует (поскольку макрос никогда не выполнялся раньше), поэтому ссылка остается такой, как есть, &email. Тогда неявный %eval() видит &email = 1 и жалуется, потому что похоже, что вы сравниваете текст (&email) с числом (1).

Вводя %global следует избегать, если это возможно. Я бы полностью избавился от %include. намного проще, ниже есть. : -)

%macro doSomething(email=);                  
  %if &email = a@b.c %then %do;       
    %put THIS RESOLVED AT 1;      
  %end; %else %if &email = d@e.f %then %do; 
    %put THIS RESOVLED AT 2;      
  %end;                           
  %put _user_;                    
%mend doSomething;                   


data emails;
  email="a@b.c"; output;
  email="d@e.f"; output;
run;

data _null_;
  set emails;
  call execute(catx(email, '%doSomething(email=', ')'));
run;

/* on log
THIS RESOLVED AT 1
DOSOMETHING EMAIL a@b.c
THIS RESOVLED AT 2
DOSOMETHING EMAIL d@e.f
*/
...