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?”

questionAnswers(4)

yourAnswerToTheQuestion