Jakie są poprawne semantyki zamknięcia na zmiennej pętli? [Zamknięte]
Rozważ następujący kod lua:
f = {}
for i = 1, 10 do
f[i] = function()
print(i .. " ")
end
end
for k = 1, 10 do
f[k]()
end
Spowoduje to wydrukowanie liczb od 1 do 10. W tym przypadkui
jest zamknięta nad wartością dla każdej iteracji zewnętrznej pętli. W ten sposób zawsze rozumiałem zamknięcia i byłem bardzo szczęśliwy ...
... dopóki nie przenosiłem kodu lua do c # i próbowałem zrobić to samo:
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]();
}
A teraz otrzymuję 10 razy wydrukowaną 10 razy (zapomnijmy, że tablice lua są oparte na 1). Zdarza się, że w tym przypadku zamknięcie działa na zmiennej, a nie na jej wartości, co ma sens, ponieważ wywoływam tylko funkcje po zakończeniu pierwszej pętli.
JavaScript wydaje się mieć tę samą semantykę (blisko zmiennej):
var f = []
for (var i = 0; i < 10; i++)
{
f[i] = function()
{
document.write(i + ' ');
};
}
for (var k = 0; k < 10; k++)
{
f[k]();
}
Właściwie oba zachowania mają sens, ale oczywiście są niekompatybilne.
Jeśli istnieje „poprawny” sposób, aby to zrobić, to albo lua, albo c # i JavaScript są błędne (jeszcze nie próbowałem z innymi językami). Moje pytanie brzmi: „jakie są„ poprawne ”semantyki zamykania zmiennej w pętli?”
edit: Nie pytam, jak to naprawić. Wiem, że mogę dodać lokalną zmienną wewnątrz pętli i zamknąć ją, aby uzyskać zachowanie lua w c # / JavaScript. Chcę wiedzieć, jakie jest teoretycznie poprawne znaczenie zamknięcia nad zapętloną zmienną, oraz punkty bonusowe za krótką listę języków, które implementują zamknięcia w każdy sposób.
edytuj: Przeformułuj moje pytanie: „jakie jest zachowanie zamknięcia nad zapętloną zmienną w rachunku lambda?”