Re[4]: Багофича C# - object initializer
От: Baiker  
Дата: 03.09.24 01:19
Оценка: :)
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Baiker, Вы писали:


B>>
B>>int Width = 7;// обычная переменная в outer scope

B>>var btn = new Button init B { // внимание! 'B' - это alias для создаваемого объекта (во внешнем scope это btn)
B>>    .Width = Width + 50;// Button.Width = Width + 50 = 57
B>>    .Invalidate();// такое MS не сделала даже за 20 лет!
B>>    .Height = .Width + 1;// очевидно, что справа от = всё тот же контекст - взяли внутреннего мембера .Width 
B>>    .Children.Add(niceIcon);
B>>    .Styles = new HTMLStyle init { // как и просили, вложенный init
B>>        .CSS = "color: #" + .Color;// Button.Color взят извне, т.к. HTMLStyle его не содержит
B>>        .File = 1;// error! Нет такого мембера ни у HTMLStyle, ни у Button, внешний scope не рассматривается
B>>        .Length = B.Length - 7;// ага! Вот где alias нужен. Вот теперь это HTMLStyle.Length = Button(B).Length - 7
B>>    };
B>>};
B>>



S>Вот видите — первый же заданный вопрос заставил вас менять синтаксис


И что в этом такого?? Я что, принёс вам готовые спеки что ли?? Глупый наезд на почве личной опупительности. НЕ НАДО на меня наезжать! Я ни вам, ни микрософту ничего не должен.
Изменил синтаксис — значит так надо, значит СТАЛО ЛУЧШЕ. Так или иначе, я предлагаю улучшать компилятор, а не бодаться с луддитами и "исторически сложилось" факапами.

S> Теперь в init появился опциональный алиас. Причём теперь нужно не забыть его указать, иначе получится бяка.


Разумеется указать! Если он нужен. А на его нужность укажет компилятор в местах с неоднозначностями. В ЧЁМ ПРОБЛЕМА-ТО?? Я не понимаю этого агрессивного противостояния — нужно ПОМОГАТЬ МНЕ решить эту синтаксическую проблему (если она вообще есть), а не выделываться здесь "мы в микрософт все умные, а вы ничего не понимаете!".

S>Двигаемся дальше. Вот у вас в .Styles не было .Color, а вот он появился. Всё, поведение кода поменялось, без малейших подсказок со стороны компилятора. Удачной отладки.


Да, это проблема. Но не такая проблема, чтобы прям осбосраться и отменить фичу! Просто надо чутка подумать и решить, как ОБЯЗАТЕЛЬНО реализовать фичу, но предусмотреть этот сложный случай.
К примеру, сам компилятор проверит, что было использование одного объекта, а после введения члена появился другой. Ни бог весть какая проблема — БЫЛО БЫ ЖЕЛАНИЕ РЕШИТЬ.

S>Коммент про .File — а что, если бы у Button было такое свойство, то всё бы скомпилировалось?


Да. В чём проблема?

S>Двигаемся дальше. В чём у нас семантика этого init?


С самого начала поста объяснил, так сложно доходит? СОКРАЩЕНИЕ КОДА.

S>1. Определён указанный выше алиас, если он есть

S>2. Разрешены только операторы присваивания и вызовы методов (причём не любых, см далее)
S>3. В аргументах методов и в выражениях операторов присваивания разрешены обращения к свойствам и методам через точку без object expression слева.

Да, всё верно.

S>Для начала нужно убедиться, что у нас нет проблем с п.3. Не будет ли конфликтов при разборе? Я пока вижу один нехороший сценарий: взаимодействие с тернарным оператором и null-checking member access. Выражения типа x > y ? .Inc() похожи и на x > (y?.Inc()), и на (x > y)?.Inc()). А теперь у нас ещё и добавляется прекрасная возможность (x > y) ? (.Inc()), то есть "Syntax error, : expected".


Решается обычным приоритетом операторов! На крайняк, НЕТ такого оператора "?␣." — есть "?.". Пробел значим. В любом случае, ЕСТЬ СКОБКИ и подсветка/подсказка. Навёл курсор на .Inc() — увидел, от кого взят мембер.


S>Способ поиска методов слева от =, справа от =, и просто при записи .Invalidate() будет отличаться?


Нет, он должен быть одинаков (как и ожидает программист, просто СОКРАЩАЯ КОД).

S> Я так понимаю, что для "справа от = " вы хотите, чтобы выполнялся поиск вверх во всех init-блоках, пока не найдется подходящий метод. Будет ли это работать также без =? То есть если я пишу btn init{.Styles init {.Invalidate()}}; — будет ли успешно вызываться btn.Invalidate()?


Разумеется! Я же привёл пример:

B>> .Invalidate();// такое MS не сделала даже за 20 лет!


Здесь нет никакого присвоения, просто ищем подходящий объект.

S>Рассматриваются ли extension-методы?


Тут я ещё не думал, но... почему бы и нет? У компилятора ВСЕГДА есть шанс сказать, когда у него неоднозначность! Скажем, если будет код:

var lst1 = new List<File>() init {
    var lst2 = new List<File>() init {
        .Sort();// чей сорт?
    }
}

...выправляем его так:
var lst1 = new List<File>() init L {
    var lst2 = new List<File>() init {
        L.Sort();// ага, знаю чей!
    }
}


S>Самое интересное тут вот в чём: как будем разруливать перегрузки методов? Вот у нас завелись два похожих метода: Button.Foo(int i), HtmlStyle.Foo(decimal d). Мы наблюдаем такое выражение: btn init{.Styles init {.Length = .Foo(42)}};. Какой из Foo будет вызван?


Согласен, тонкий И РЕДКИЙ случай — выкинем ambiguous. Что сложного-то?? Не надо пытаться сделать больше, чем позволено "тупой машине"! (иначе сделаешь только хуже)

Тут принцип построения фич простой: запиливаем фичу для большинства случаев (предварительно хорошенько рассмотрев все случаи). Если люди дадут фидбэк "вот у нас такой часто используемый код, а он лажает на вашем синтаксисе" — повторяем SDLC и допиливаем как надо (фича всё равно в АЛЬФА ТЕСТЕ!). И так до полной шлифовки.

S>Примерно к любому варианту, который вы выберете, я напишу контрпример, который работает "не так, как интуитивно ожидается".


Да ради бога! Чем больше контр-примеров, тем шире почва для обсуждения (а не отмазок НЕ ДЕЛАТЬ). Факт тот, что фичу МОЖНО и НУЖНО сделать. Я не глубокий спец именно в компиляторах, но я знаю, что если что-то делать — то оно сделается! А если в стиле Хлипперта придумывать "почему мы НЕ ХОТИМ это делать" — то ничего и не будет.
Пока что из обсуждения я не увидел НИ ЕДИНОГО аргумента "эту фичу принципиально нельзя сделать" — ВСЁ ВОЗМОЖНО, но постепенно. А вы сейчас своей ДЕМАГОГИЕЙ пытаетесь грубо говоря "закидать шапками". Так люди НЕ КООПЕРИРУТСЯ! Мыслить надо ДРУЖЕСКИ, а не сидеть как тухлый ёж и совать всем иголки.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.