metaclass: (Default)
[personal profile] metaclass
Я где-то сошел с ума, но с ходу не соображу где.

Есть такой код с замыканиями:

  class Program {

    delegate void ZeroArityFunc();

    static string[] testData=new string[] { "a", "b", "c", "d", "e", "f" };

    static void Main(string[] args) {
      List list = new List();
      foreach(string s in testData) {
        ZeroArityFunc f = () => Console.Write(s); //создаем лямбду и присваиваем ее f
        list.Add(f);
      }

      foreach(ZeroArityFunc a in list) {
        a();
      }

    }
  }



Т.е. я пытаюсь сделать следующее: создать список функций без параметров, которые при вызове будут выдавать результаты от a до f. Это вообще имитация другого, рабочего кода, но суть та же самая.

А теперь внимание, ШИЗА: этот код выдает "f f f f f f", а не то, что я от него хочу ("a b c d e f"). Т.е. делегаты в списке каким-то чудесным образом начинают ссылаться не 6 разных экземпляров замыканий, а на один.

Что-то мне это начинает необъяснимо напоминать недавний пост [livejournal.com profile] alexclear про JavaScript, я сейчас для смеха попробую тамошний workaround.

PS: Жопа, workaround оттуда сработал. В кошмарном сне бы такое не привиделось, что непонятный пост про совершенно неизвестный мне язык через неделю окажется пригодным в работе.

PPS: Оказывается, известная шиза - переменная цикла s объявлена один раз и до цикла, и замыкается оно на нее.

Date: 2010-08-14 06:15 pm (UTC)
From: [identity profile] skiminog.livejournal.com
Нельзя замыкаться на переменную цикла. Это же Боян из Боянов.
http://habrahabr.ru/blogs/net/36601/

Date: 2010-08-14 06:16 pm (UTC)
From: [identity profile] metaclass.livejournal.com
Оооо, теперь дошло. :)
Ну слава богу, я псих, а не дотнет.

Date: 2010-08-14 07:10 pm (UTC)
From: [identity profile] antilamer.livejournal.com
Решарпер даже ворнинг выдает на такое.

Date: 2010-08-14 06:17 pm (UTC)

Date: 2010-08-14 06:19 pm (UTC)
From: (Anonymous)
Все тут хорошо. Замыкние указывает на переменую S, но во время вызона замыкание S указывает уже на последний делегат (во всех делегатах это одна и таже S).

Этот случай даже был описан в Этюдах на C# от Эрика Липперта:
http://habrahabr.ru/blogs/net/98779/

Date: 2010-08-14 06:41 pm (UTC)
From: [identity profile] zamotivator.livejournal.com
Ты замыкаешь бокс, а не копию переменной.

Date: 2010-08-14 06:41 pm (UTC)
From: [identity profile] zamotivator.livejournal.com
Я аналогично в Питоне хуел от лексических замыканий :)

Date: 2010-08-14 07:07 pm (UTC)
From: [identity profile] metaclass.livejournal.com
Не, строка не боксится - она сама по себе reference value.

Date: 2010-08-14 07:12 pm (UTC)
From: [identity profile] zamotivator.livejournal.com
Ну вот и ответ, чо

Date: 2010-08-14 07:17 pm (UTC)
From: [identity profile] metaclass.livejournal.com
Нее, если сделать
string workaround = s;
и замкнуться на workaround - все работает. При том, что это все равно копирование ссылки, но семантика замыкания меняется.

Date: 2010-08-14 07:18 pm (UTC)
From: [identity profile] zamotivator.livejournal.com
А, т.е. всё-таки замыкание работает как лексическое. Понял.

Date: 2010-08-14 07:20 pm (UTC)
From: [identity profile] metaclass.livejournal.com
Я думаю, с такой херней или наших работодателей заказчики пошлют, или нас работодатели, или же нам обеспечено трудоустройство до пенсии и позже :)

Потому что альтернативы в виде "позвать ребе [livejournal.com profile] theiced и переписать на лиспе все" или "взять 1000 тупых студентов РТИ и одного нетупого" они не осилят.

Date: 2010-08-14 07:21 pm (UTC)
From: [identity profile] zamotivator.livejournal.com
Не, это разовая работа - просто я не хочу руками дохуя замен делать, я это автоматизирую.
В скрипты это никуда не попадёт, просто разовая работа :)

Date: 2010-08-14 06:45 pm (UTC)
From: [identity profile] honeyman.livejournal.com
Гы, вот ровно вчера то же самое писал, но про Python (http://habrahabr.ru/blogs/crazydev/101715/#comment_3154402).

Date: 2010-08-14 10:39 pm (UTC)
From: [identity profile] zamotivator.livejournal.com
Блин, ребята, да это же банальная работа с лексическими замыканиями, ну стыдно же, а :)

Date: 2010-08-14 07:34 pm (UTC)
From: [identity profile] max630.livejournal.com
afair java при засовывании переменной в анонимный класс требует чтобы она была final. Причём это чуть ли не error.

Date: 2010-08-14 07:36 pm (UTC)
From: [identity profile] max630.livejournal.com
так что можно попробовать обойтись простым "s2 = s;", и его уже засовывать.

Date: 2010-08-14 07:38 pm (UTC)
From: [identity profile] alpha-cygnus.livejournal.com
Do not use mutability ;-)
Замыкается переменная, а не значение. А потом она используется, одна и та же на все замыкания. Замыканий-то много, а переменная в них одна.

Date: 2010-08-14 07:44 pm (UTC)
From: [identity profile] w00dy.livejournal.com
ребе, вас var и System.Action пользовать не учили?

Date: 2010-08-14 07:48 pm (UTC)
From: [identity profile] metaclass.livejournal.com
У меня часть кода со времен 2003 студии и 1.1 дотнета живет.
А это все счастье только в 3.5 появилось. К тому времени я уже половину всех этих типов сам написал :)

Date: 2010-08-14 08:10 pm (UTC)
From: [identity profile] w00dy.livejournal.com
Никто не мешает пользовать это всё в 2.0, вы же вот пользуете лямбды, а var и Action - нет.

Date: 2010-08-14 08:18 pm (UTC)
From: [identity profile] metaclass.livejournal.com
В компиляторе 2005 студии не было этого дела, поэтому по привычке использую то что помню :)
Про System.Action я вообще не знал, а var использую только когда типы слишком заебенные чтобы их руками писать, или когда у них вообще тип автоматический.

Date: 2010-08-14 08:47 pm (UTC)
From: [identity profile] w00dy.livejournal.com
Тогда ещё узнайте о System.Func и клоны. А var - имхо если и пользовать, то везде. А тип пусть выводит компилятор, студия и всякие тулзени аля R# и прочие, не барское это дело.

Date: 2010-08-14 08:57 pm (UTC)
From: [identity profile] metaclass.livejournal.com
System.Func я знаю.
Вот чего я не знаю так это как синоним типа в C# написать и меня это бесит :)

Date: 2010-08-14 10:57 pm (UTC)
From: [identity profile] w00dy.livejournal.com
а зачем вам синонимы? Мне лично ни разу не требовалось что-то такое.

Date: 2010-08-14 11:26 pm (UTC)
From: [identity profile] feorex.livejournal.com
А что такое синоним типа? Алиас?
using int = System.Int32;
не?

Date: 2010-08-14 07:47 pm (UTC)
From: [identity profile] alexandr0.livejournal.com
Ну так мутабельность как бы намекает, что следует быть настороже :)

Date: 2010-08-14 09:44 pm (UTC)
From: [identity profile] hshhhhh.livejournal.com
поиграл я в ваш UT.
компьютер у меня дикое говно, тормозит безбожно, но тем не менее суть игры понятна: UT прекрасный заменитель контре, но вот warsow прекрасный заменитель кваке, подинамичнее так. обе хорошие.

Date: 2010-08-15 12:58 pm (UTC)
From: [identity profile] avr-forever.livejournal.com
А вот писали бы Вы, ребе, на тикле, проблем бы таких не было. Там чёткий порядок подстановок, потому всегда ясно, будет использоваться переменная либо её значение.

Profile

metaclass: (Default)
metaclass

April 2017

S M T W T F S
      1
2345678
9101112 131415
16171819202122
23242526272829
30      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jun. 15th, 2025 01:36 pm
Powered by Dreamwidth Studios