您得到的答案 (20&an) 是正确的 - 一切就绪。你甚至不需要阅读我发布的这个答案的其余部分:-)
但是我注意到您对 & 和 && 有点困惑。如果您想了解更多,我整理了一些关于& 和&& 之间区别的额外信息,以及&& 在SAS 宏评估中的用途。
& 是最常见的符号 - 您只需使用它来评估/取消引用变量。所以:
%LET an = 14 ;
%PUT ----- an ;
%PUT ----- &an ;
输出:
----- an
----- 14
如您所见,您必须在变量名之前放置一个& 才能取消对其值的引用。省略& 只会打印字符串an,在这种情况下恰好是变量的名称。对于大多数宏编码,& 是您所需要的。 SAS 宏中的 & 就像 shell 中的 $,C 中的 * 等等。
现在,&& 是干什么用的?它的存在使您能够拥有动态宏变量名称。也就是说,有一个宏变量,其值为另一个宏变量的名称。如果你熟悉 C,你可以把它想象成一个指向指针的指针。
SAS 评估&& 的方式分为两遍。在第一遍中,它将&& 转换为&。同时,它在该通道中看到的任何& 符号都将用于取消引用它们旁边的变量名称。这个想法是让后面的这些表达式解析为一个变量名。然后,在第二遍中,剩余的 & 符号(最初都是 && 符号)取消引用它们现在发现自己旁边的任何变量名称。
这是一个示例输出示例:
%LET x = 3;
%LET name_of_variable = x;
%PUT ----- &x;
%PUT ----- &&name_of_variable;
%PUT ----- &&&name_of_variable;
输出:
----- 3
----- x
----- 3
在第一个%PUT 中,我们只是使用普通的旧&,因此我们正在做我们之前所做的,读取并打印x 持有的值。在第二个%PUT 中,事情变得更有趣了。由于&&,SAS 进行了两次评估。第一个转换这个:
%PUT ----- &&name_of_variable;
到这里
%PUT ----- &name_of_variable;
在第二遍中,SAS 执行标准的& 评估以打印name_of_variable 中保存的值 - 字符串x,它恰好是我们正在使用的另一个变量的名称。当然,这个例子特别做作:你本来可以写&name_of_variable,为什么还要写&&name_of_variable?
在第三个%PUT 中,我们现在有&&&,SAS 执行了两次传递。在这里,我们终于看到了&& 的真正目的。我将把表达式的部分放在括号中,这样你就可以看到它们是如何计算的。我们从这里开始:
%PUT ----- (&&)(&name_of_variable);
到这里:
%PUT ----- &x;
所以在第一遍中,&& 被转换为&,而&name_of_variable 是对name_of_variable 的简单取消引用,评估它所持有的内容,正如我们所说的@ 987654367@.
所以在第二遍中,我们只剩下简单的评估:
%PUT ----- &x;
由于我们将 x 设置为 3,因此计算结果为 3。
所以从某种意义上说,&&&name_of_variable 是在说“显示名称存储在 name_of_variable. 中的变量的值”
这是一个激励性的示例,说明您为什么要这样做。假设您有一个简单的宏子例程,它将任意数字添加到存储在 SAS 宏变量中的数值上。为此,子例程必须知道要添加的数量,但更重要的是,它需要知道要添加的变量的名称。您可以通过&& 机制完成此动态变量命名,如下所示:
%MACRO increment_by_amount (var_name = , amount = );
%LET &var_name = %EVAL (&&&var_name + &amount) ;
/* Note: this could also begin with %LET &&var_name = .... */
%MEND;
这里我们说:“让名称保存在var_name(即&var_name)中的变量等于名称保存在var_name(即&&&var_name)中的变量的值加上保存的值在amount(即&amount)。
当您调用这样的子例程时,请确保您传递的是变量 name,而不是值。也就是说,这样说:
%increment_by_amount (var_name = x , amount = 3 );
不是这个:
%increment_by_amount (var_name = &x , amount = 3);
所以调用的一个例子是:
%LET x = 3;
%PUT ----- &x;
%increment_by_amount (var_name = x , amount = 3 );
%PUT ----- &x;
输出:
----- 3
----- 6