2

这个问题纯粹出于求知欲。

相对经常浏览 Python 部分后,我看到了许多与此类似的问题其中有人要求以编程方式定义全局变量。他们中的一些人意识到 的陷阱exec,而其他人则没有。

但是,我最近一直在 Stata 中进行编程,以下是常见的:

local N = 100
local i = 1

foreach x of varlist x1 - x`N' {
    local `x' = `i' * `i'
    ++i 
}

在 Stata 的说法中,N创建了一个具有名称的本地宏,并N计算为 100。在循环的每次迭代中foreach,从x1to的值x100被分配给本地宏x。然后,循环内的行将 的平方分配i给 的扩展x,这是一个与 结尾相同的局部宏i。也就是这个循环x4展开到4^2后,又x88展开到88^2。

在 Python 中,做类似事情的方法是:

squares = {}

for x in range(1,101):
    squares[x] = x**2

然后squares[7]等于 7^2。

这是一个非常简单的例子。stata 宏还有很多其他用途。您可以将它们用作传递要评估的函数的一种方式,例如:

local r1 "regress"
local r2 "corr"

foreach r of varlist r1-r2 {
     ``r'' y x
}

周围的双刻度线r将该宏扩展了两次,首先是r1/r2然后是regress/ corr,结果是运行线性回归,y作为因变量和x作为自变量,然后显示 和 之间的相关yx。更复杂的东西是可能的。

我的问题基本上是,stata 是否属于更大的语言类别,其中变量赋值/评估采用这种“宏赋值/扩展”形式?任何解释为什么会这样设计一种语言,和/或其他语言中类似结构的例子的加分点。

4

4 回答 4

3

这实际上只是一个存在多少语法糖的问题。在任何有价值的语言中,您都可以使用映射或字典数据结构在运行时创建具有某些值的变量名(键)。某些语言可能比其他语言更透明地将其与普通变量标识符集成。

于 2011-03-04T04:48:44.597 回答
3

(对不起,这是一个“答案”,而不是评论……人们不评价我的答案,所以我没有足够的分数来评论这个问题。)

首先,让我指出 Stata 的奇怪之处在于它会在执行该行代码之前翻译宏。例如:

说你打字。

local x3 = 20 
local y = 3 
display "I am `x`y'' years old"

在内部,Stata 将翻译本地(从内到外),然后执行display命令。也就是说,Stata会翻译命令

display "I am `x3' years old"

然后

display "I am 20 years old"

然后,Stata 将实际执行最后一行代码。您可以通过首先执行以下命令来观看所有这些: set trace on.

有细微的差别。括号` '更改命令。我认为这实际上与其他编程语言不同。您通常可以在 Stata 中用一行代码来做某事,而其他语言需要两行代码(一行用于“扩展”宏;另一行用于执行代码行)。

有用的是Stata还可以计算括号内的各种表达式` '(只要它们返回一个数字或字符串......例如,没有返回矩阵)

display "I am `= 2011 - 1991' years old"
display "I am `= floor(uniform()*`x`y'')' years old"

一旦你习惯了,这将非常有用。宏使 Stata 中的东西比您在 SAS 中所做的更干净SAS 的%let声明几乎没有那么灵活。

我还要指出一些错误。

(1) 在这些示例中,循环设置错误。x1, x2, ... , x100 是宏(局部变量),而不是变量。你不能说foreach x of varlist x1 - x100因为x1-x100不是变量列表。如果我试图这样做,我可能会使用:

local N = 100
forvalues i = 1/`N' {
    local x`i' = `i' * `i'
}

第二个例子也犯了同样的错误。 r1并且r2不是变量。你可以这样做:

local mycommands regress corr 
foreach r in `mycommands' {
     `r' y x
}

(尽管我实际上会键入等效的 , foreach r of local mycommands { ... },据说执行起来要快一些)。

(2) 二、 ++i 无效。你可能是想说local ++i

于 2011-03-04T16:17:31.377 回答
2

我不知道这是否是您正在寻找的,但在 PHP 中您可以执行以下操作:

for ($i=0; $i<10; $i++) {
    ${x.$i} = $i*$i;
}

print $x3; // prints 9
print $x4; // prints 16

我个人觉得这很不愉快。

于 2011-03-04T04:53:10.380 回答
1

Javascript 就是一个明显的例子,尽管机制类似于 Python,而不是 Stata。

for(var i = 0; i < 100; i++)
    this["var" + i] = i * i;

alert(var8); // 64
于 2011-03-04T04:51:10.600 回答