Несогласованный тип данных макропеременной

Я пытаюсь сделать простой макрос, который проверяет, отсутствует ли конкретная переменная макроса или не существует. Обычно для этого требуются два оператора: %symexist и, если он существует, дополнительная логика для определения, является ли это нулевым значением. Приведенный ниже код объединяет все это в одно целое.

%macro isnull(macvar);
    %sysevalf(%superq(%superq(macvar)) NE %str(), boolean);
%mend isnull;

Проблема

Я не могу использовать %isNull() в операторе %if, потому что возвращаемое значение всегда кажется символом. Это поведение различается в открытом коде или в самом макросе.

Что я пробовал

Я сузил его до макроса, который не разрешается как числовое значение. Я перепробовал все, от заключения с %sysfunc(putn()) до %cmpres() до %sysfunc(compress()). Если это открытый код, он числовой. Если это в другом макросе, это персонаж. Вы можете увидеть это с помощью этого кода:

/* Miss2 resolves incorrectly as character */
%macro check;
    %let miss1=%sysevalf(%superq(asdf) =, boolean);
    %let miss2=%isNull(asdf);

    %put Miss1: %datatyp(&miss1);
    %put Miss2: %datatyp(&miss2);
%mend;
%check;

/* Miss2 resolves correctly as numeric */
%let miss1=%sysevalf(%superq(asdf) =, boolean);
%let miss2=%isNull(asdf);

%put Miss1: %datatyp(&miss1);
%put Miss2: %datatyp(&miss2);

Хочу

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

%macro foo;
    %if(%isNull(sysuserid) = 1) %then %put sysuserid exists;
    %if(%isNull(asdffdsa) = 0) %then %put asdffdsa does not exist;

    %if(%isNull(sysuserid) > 0) %then %put this should resolve;
    %if(%isNull(asdffdsa) > 0) %then %put this should not resolve;
%mend;
%foo;

person Stu Sztukowski    schedule 02.05.2017    source источник
comment
Если взглянуть на это, но начну с заблуждения, макропеременные не имеют «типов» - это весь текст.   -  person Joe    schedule 02.05.2017
comment
Если вы хотите рассматривать% MISSM () как функцию, она не может генерировать точку с запятой !!   -  person Tom    schedule 02.05.2017


Ответы (1)


Проблема в том, что в вашем макросе есть точка с запятой. Видеть это:

174  %macro check;
175      %let miss1=%sysevalf(%superq(asdf) NE %str(), boolean);
176      %let miss2=%missm(asdf);
177
178      %put &miss1. Miss1: %datatyp(&miss1);
179      %put &miss2. Miss2: %datatyp(%unquote(&miss2));
180  %mend;
181  %check;
WARNING: Apparent symbolic reference ASDF not resolved.
WARNING: Apparent symbolic reference ASDF not resolved.
0 Miss1: NUMERIC
0; Miss2: CHAR

Обратите внимание на ;? Вместо этого скомпилируйте это:

%macro missm(macvar);
    %sysevalf(%superq(%superq(macvar)) NE %str(), boolean)
%mend missm;

и вы получите:

185  %macro check;
186      %let miss1=%sysevalf(%superq(asdf) NE %str(), boolean);
187      %let miss2=%missm(asdf);
188
189      %put &miss1. Miss1: %datatyp(&miss1);
190      %put &miss2. Miss2: %datatyp(%unquote(&miss2));
191  %mend;
192  %check;
WARNING: Apparent symbolic reference ASDF not resolved.
WARNING: Apparent symbolic reference ASDF not resolved.
0 Miss1: NUMERIC
0 Miss2: NUMERIC

Еще добавлю, что, думаю, не стоит пропускать %symexist. Вы получаете предупреждение в журнале, как вы это делаете здесь, этого легко избежать.

%macro missm(macvar);
  %if %symexist(&macvar.) %then
    %sysevalf(%superq(%superq(macvar)) NE , boolean)
  %else
    0 
%mend missm;

Вы также заметите, что я удаляю ненужный %str(), который на самом деле ничего не делает. См. Основополагающую статью Чан Чанга, Is This Macro Parameter Blank, чтобы узнать, почему (и для некоторых больше интересной информации, если вы ее еще не читали).

Наконец, я бы посоветовал переименовать макрос и / или изменить направление. %if %missm говорит мне, «если эта макропеременная отсутствует», что противоположно тому, что вы говорите: TRUE возвращается, если она НЕ отсутствует. %missm должен возвращать истину для EQ [пусто], или НЕ %symexist; он должен возвращать false для [определено и содержит значение].

person Joe    schedule 02.05.2017
comment
Точка с запятой снова отображается. Отличный ответ, спасибо! - person Stu Sztukowski; 02.05.2017
comment
@StuSztukowski Если вы собираетесь переименовать его, чтобы было понятнее, я большой поклонник использования таких имен, как isMissing() или is_missing, так что когда они следуют за заявлением if, оно почти читается как обычный английский. - person Robert Penridge; 03.05.2017
comment
Я внес предложенные изменения и отредактировал исходную проблему. Спасибо! - person Stu Sztukowski; 05.05.2017