Изменение значения переменной макроса внутри макроса SAS

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

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

   %put &variable1;
 %mend macro1;

 %macro1;

2 ответов


у вас есть пару вопросов здесь. Прежде всего, вам не хватает % перед вызовом macro2, но я подозреваю, что это просто опечатка. Основная проблема заключается в том, что вы пытаетесь сделать то, что на других языках называется вызов по ссылке. Вы можете сделать это в макросе 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, который имеет объяснение &&& синтаксис; вы можете посмотреть здесь. Обратите внимание, что %EVAL вызов не имеет ничего общего с вызовом по ссылке, он просто там, чтобы сделать добавление.


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=%macrostuff(); не может быть 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;

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