不一致的宏变量数据类型
Inconsistent Macro Variable Data Type
我正在尝试制作一个简单的宏来检查特定的宏变量是否丢失或不存在。通常,这需要两个语句:一个 %symexist
,如果它确实存在,则需要额外的逻辑来检测它是否为空值。下面的代码将所有这些合二为一。
%macro isnull(macvar);
%sysevalf(%superq(%superq(macvar)) NE %str(), boolean);
%mend isnull;
问题
我不能在 %if
语句中使用 %isNull()
,因为返回值似乎总是一个字符。如果它在开放代码中或在宏本身中,则此行为会有所不同。
我试过的
我已将其缩小到未解析为数值的宏。我已经尝试了从 %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;
你这里的问题是你的宏中有一个分号。看到这个:
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()
,它实际上没有任何作用。请参阅 Chang Chung 的开创性论文 Is This Macro Parameter Blank,了解原因(如果您尚未阅读它,还可以了解更多重要信息)。
最后 - 我想我会建议重命名您的宏 and/or 反转方向。 %if %missm
对我说 'if this macro variable is missing',这与您所说的相反:如果不丢失,则 return 为 TRUE。 %missm
应该 return 对于 EQ [空白] 为真,否则 %symexist
;对于[已定义并包含一个值],它应该 return false。
我正在尝试制作一个简单的宏来检查特定的宏变量是否丢失或不存在。通常,这需要两个语句:一个 %symexist
,如果它确实存在,则需要额外的逻辑来检测它是否为空值。下面的代码将所有这些合二为一。
%macro isnull(macvar);
%sysevalf(%superq(%superq(macvar)) NE %str(), boolean);
%mend isnull;
问题
我不能在 %if
语句中使用 %isNull()
,因为返回值似乎总是一个字符。如果它在开放代码中或在宏本身中,则此行为会有所不同。
我试过的
我已将其缩小到未解析为数值的宏。我已经尝试了从 %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;
你这里的问题是你的宏中有一个分号。看到这个:
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()
,它实际上没有任何作用。请参阅 Chang Chung 的开创性论文 Is This Macro Parameter Blank,了解原因(如果您尚未阅读它,还可以了解更多重要信息)。
最后 - 我想我会建议重命名您的宏 and/or 反转方向。 %if %missm
对我说 'if this macro variable is missing',这与您所说的相反:如果不丢失,则 return 为 TRUE。 %missm
应该 return 对于 EQ [空白] 为真,否则 %symexist
;对于[已定义并包含一个值],它应该 return false。