2015-06-15 3 views
7

Я определяю макрокоманду внутри макроса. Затем я кормлю его вторым макросом. Внутри счетчика macro2 изменяется значение до 200. Однако, когда я проверяю, что находится внутри макропеременной, которую я вставляю после запуска макроса 2, он все еще говорит 0. Я хотел бы, чтобы он сохранил значение 200? Это возможно?Изменение значения макроса Переменная внутри макроса SAS

%macro macro1(); 
    %let variable1= 0; 
    macro2(counter=&variable1) 

    %put &variable1; 
%mend macro1; 

%macro1; 

ответ

9

У вас есть пара вопросов здесь. Прежде всего, вам не хватает % до вашего звонка до macro2, но я подозреваю, что это только опечатка. Основная проблема заключается в том, что вы пытаетесь сделать то, что упоминается на других языках, как call-by-reference. Вы можете сделать это в макросе SAS, передав имя вашей переменной, а не значение вашей переменной, а затем используйте некоторый фанковый синтаксис &, чтобы установить переменную этого имени в новое значение.

Ниже приведен пример кода, который делает это:

%macro macro2(counter_name); 
    /* The following code translates to: 
    "Let the variable whose name is stored in counter_name equal 
    the value of the variable whose name is stored in counter_name 
    plus 1." */ 

    %LET &counter_name = %EVAL (&&&counter_name + 1); 

%mend; 

%macro macro1(); 
    %let variable1= 0; 

    /* Try it once - see a 1 */ 
    /* Notice how we're passing 'variable1', not '&variable1' */ 
    %macro2(counter_name = variable1) 
    %put &variable1; 

    /* Try it twice - see a 2 */ 
    /* Notice how we're passing 'variable1', not '&variable1' */ 
    %macro2(counter_name = variable1) 
    %put &variable1; 
%mend macro1; 

%macro1; 

Я на самом деле есть еще один пост на StackOverflow, что имеет объяснение синтаксиса &&&; вы можете have a look at it here. Обратите внимание, что вызов %EVAL не имеет ничего общего с вызовом по ссылке, он просто должен сделать добавление.

+1

Спасибо, сделана точка ... Я немного подкорректирую язык. –

+1

Спасибо за обновление! – Joe

+1

Спасибо, что имеет смысл, я думаю. Я попробую завтра. Тем не менее, мне интересно, не означает ли это, что макрос2 не может быть достаточно общим, чтобы принимать значения или макропеременные. Как написано выше, теперь он ограничивается только взятием макропеременных? – DanRoDuq

2

Sparc_Spread объясняет, как «вызвать по ссылке» на языке макросов SAS, который может решить вашу проблему.

В этом конкретном случае, однако, не обязательно использовать вызов по ссылке, и я бы сказал, что он не является идиоматическим для макроса языка SAS, чтобы использовать его (хотя, конечно, ничего не случилось с ним - он выглядит немного странно, и это немного сложнее, так как это не настоящая нация, хотя, конечно, намеренно поддерживается, если это необходимо). Есть два способа обойти это, что они очень просты в использовании.

Прежде всего, предположим, вы знаете имя переменной, которое хотите увеличить, а начальное значение - это только интересная вещь. Благодаря тому, как макрос SAS обрабатывает область охвата, с чем-то не совсем лексическим охватом и не совсем функциональным, он автоматически будет использовать переменную, которая уже существует в самой локальной области, когда она уже существует (с некоторыми незначительными оговорками, например с использованием макросов DOSUBL).

Так что это работает, как ожидалось:

%macro macro2(counter=); 
    %do variable1 =&counter. %to 200; 
    %if %sysfunc(mod(&variable1.,50))=0 %then %put &=variable1; 
    %end; 

%mend macro2; 

%macro macro1(); 
    %let variable1= 0; 
    %macro2(counter=&variable1.); 

    %put &=variable1; 
%mend macro1; 

%macro1; 

(Конечно, то есть, если вы ожидаете & variable1 иметь значение 201 - потому %do петли, как do петли, всегда получают приращение один выше, чем их . конечное значение Я полагаю, ваша реальная процедура работает по-разному)

это потому, что &variable1. упоминается в %macro2 автоматически является один присутствует в самой локальной области видимости. - что в данном случае объем %macro1.


В качестве альтернативы, если вы используете эту %macro2 с целью инкремент счетчика, я хотел бы использовать метод function-style macro.

Макрос в стиле функции по определению - это тот, который возвращает только одно значение - и returns Я имею в виду одно значение в конце кода макроса, которое представлено в виде простого текста (поскольку макрос, в конце концов, , предназначенный только для создания текста, который затем анализируется обычным парсером SAS-языка).

Это можно затем использовать в правой части знака равенства в инструкции присваивания. Ключ состоит в том, что он использует только элементы макроязыка - %do и т. Д., А также язык данных, proc и т. Д., Что помешало бы ему находиться на правой стороне знака равенства в присваивании (т. Е. не может x=proc sql(select...)).

Итак, следующее достижение цели: увеличивайте счетчик на некоторое количество, верните значение (201, в этом случае, как и раньше), а затем это можно присвоить макропеременной.

%macro macro2(counter=); 
    %do internal_counter =&counter. %to 200; 
    %if %sysfunc(mod(&internal_counter.,50))=0 %then %put &=internal_counter.; 
    %end; 
    &internal_counter. 
%mend macro2; 

%macro macro1(); 
    %let variable1= %macro2(counter=0); 

    %put &=variable1; 
%mend macro1; 

%macro1; 

Я предположил бы, что это наиболее идиоматическим способ для достижения этой цели, и самый простой: вы передаете значение, которое вы хотите в качестве входных данных, функция работает на нем, возвращает значение, которое вы затем присвоить переменный в вашем макросе, но вы хотите.

+0

+1 это также решает проблему. Я никогда не знал о синтаксисе '& ='! Очень полезно для отладки и т. Д. Это всегда было в SAS? Я читал книгу фиолетового Карпентера несколько раз, и я не думаю, что когда-либо сталкивался с ней. –

+1

'& =' новый от 9.3 Я думаю (или, может быть, 9.2) - это приятная мелочь! – Joe

+0

Это точно. Спасибо, что опубликовали его! –

Смежные вопросы