什么是封闭在一个循环变量的正确的语义? [英] What are the correct semantics of a closure over a loop variable?
问题描述
考虑以下Lua代码:
<预类=郎LUA prettyprint-覆盖>
F = {}
对于i = 1,10做
F [I] =功能()
打印(我...)
端
端
对于k = 1,10做
F [K]()
端
此打印从1到10的数字。在这种情况下, I
被关闭在为外部循环的每次迭代的值。这是我一直明白倒闭了,我很高兴......
......直到我被移植了一些Lua代码到C#,我试图做同样的事情:
<预类=郎CSHARP prettyprint-覆盖>
变种F =新的操作[10];
的for(int i = 0;我小于10;我++)
{
F [I] =(新动作(委托()
{
Console.Write第(i +);
}));
}
的for(int k = 0; K< 10; k ++)
{
F [K]();
}
而现在我得到的印刷数量10倍(让我们忘记了LUA阵列是基于1)。它实际发生,在这种情况下,封闭件的工作原理上,这使得有很大的意义,因为我只调用函数一旦第一循环结束的变量,而不是它的值,
JavaScript的似乎有相同的语义(接近过变量):
<预类=郎咸平的JavaScript prettyprint-覆盖>
变种F = []
为(VAR I = 0;我小于10;我++)
{
F [I] =功能()
{
的document.write第(i +'');
};
}
为(VAR K = 0; K< 10; k ++)
{
F [K]();
}
其实,这两种行为做出很大的意义,但是当然是不相容的。
如果有一个正确的方式做到这一点,那么无论LUA,或C#和JavaScript是错误的(我还没有与其他语言的尝试还)。所以我的问题是:什么是正确
编辑闭合循环中变量的语义?:我不是问如何修理这。我知道我可以添加一个局部变量的循环中,并关闭了一个获得在C#/ JavaScript中的LUA行为。我想知道什么是关闭的理论上正确含义在一个环形变量,以及加分,其中语言实现每路封闭的短名单。
编辑:要重组我的问题:什么是关在一个环形变量演算的行为
中的Lua手册解释到底为什么这个工程。它描述了一个while循环,因为这方面的for循环索引:
为V = E1,E2,E3做块结束
--Is等价于:
做
局部变量,限制步= tonumber(E1),tonumber(E2),tonumber(E3)
如果不(var和极限和工序),然后误差()结束
同时(步骤> 0和变种&下; =极限)或(步骤下; = 0和变种> =极限)做
当地时间v =变量
地块
VAR = VAR +步
端
端
注意,此时的循环变量 v
声明的 的内部范围的而
循环。这是专门做来允许你在做什么。
Consider the following lua code:
f = {}
for i = 1, 10 do
f[i] = function()
print(i .. " ")
end
end
for k = 1, 10 do
f[k]()
end
This prints the numbers from 1 to 10. In this case, i
is closed over the value for each iteration of the outer loop. This is how I had always understood closures, and I was very happy...
...until I was porting some lua code into c#, and I tried to do the same thing:
var f = new Action[10];
for (int i = 0; i < 10; i++)
{
f[i] = (new Action(delegate()
{
Console.Write(i + " ");
}));
}
for (int k = 0; k < 10; k++)
{
f[k]();
}
And now I get the number 10 printed 10 times (let's forget that lua arrays are 1-based). It actually happens that in this case, the closure works over the variable, not its value, which makes a lot of sense, since I'm only calling the functions once the first loop is over.
JavaScript seems to have the same semantics (close over the variable):
var f = []
for (var i = 0; i < 10; i++)
{
f[i] = function()
{
document.write(i + ' ');
};
}
for (var k = 0; k < 10; k++)
{
f[k]();
}
Actually, both behaviors make a lot of sense, but are of course incompatible.
If there is a "correct" way to do this, then either lua, or c# and JavaScript are wrong (I haven't tried with other languages yet). So my question is: "what are the "correct" semantics of closing a variable inside a loop?"
edit: I'm not asking how to "fix" this. I know I can add a local variable inside the loop and close over that one to get the lua behavior in c#/JavaScript. I want to know what is the theoretically correct meaning of closing over a looped variable is, and bonus points for a short list of which languages implement closures in each way.
edit: To rephrase my question: "what is the behavior of closing over a looped variable in lambda calculus?"
The Lua manual explains exactly why this works. It describes the index for-loop in terms of a while loop as this:
for v = e1, e2, e3 do block end
--Is equivalent to:
do
local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
if not (var and limit and step) then error() end
while (step > 0 and var <= limit) or (step <= 0 and var >= limit) do
local v = var
block
var = var + step
end
end
Notice how the loop variable v
is declared inside the scope of the while
loop. This is done specifically to allow exactly what you're doing.
这篇关于什么是封闭在一个循环变量的正确的语义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!