Здравствуйте, AlexRK, Вы писали:
ARK>Абсолютно никакой разницы. В случае def/let будет то же самое. А если человек попробует после "def a" написать "a = null;" — ошибка компиляции.
Ну так вот подтверждение что есть разница.
var дает возможность менять переменную потом несколько раз, а инициализация сразу через def/let не дает.
Так можно
var a;
using(var res = GetRes())
{
a = res.Foo();
}
a = null; // :maniac:
А так будет нельзя
def a = using(res = GetRes()) res.Foo();
a = null; // Ошибка компиляции
Здравствуйте, _NN_, Вы писали:
_NN>Ну так вот подтверждение что есть разница. _NN>var дает возможность менять переменную потом несколько раз, а инициализация сразу через def/let не дает.
_NN>Так можно _NN>
_NN>var a;
_NN>using(var res = GetRes())
_NN>{
_NN> a = res.Foo();
_NN>}
_NN>a = null; // :maniac:
_NN>
Здравствуйте, AlexRK, Вы писали:
ARK>Да БЛИН. Еще раз говорю, никакой разницы не будет.
ARK>
ARK>def a;
ARK>using(var res = GetRes())
ARK>{
ARK> a = res.Foo();
ARK>}
ARK>a = null; // Ошибка компиляции
ARK>Короче должно быть ровно одно присваивание в каждом ветвлении.
Это конечно похоже, но другое.
Вы предлагаете вариант, где можно изменить значение только один раз, а я говорю о том что проще когда вообще нет возможности поменять значение.
У вашего предложения есть хорошее применение, например в out аргументах.
Однако в данном случае я не вижу никакого смысла разделять определение переменной и инициализацию.
Здравствуйте, _NN_, Вы писали:
_NN>Это конечно похоже, но другое. _NN>Вы предлагаете вариант, где можно изменить значение только один раз, а я говорю о том что проще когда вообще нет возможности поменять значение.
Нет, я предлагаю вариант, где значение задается только один раз и больше не меняется. Просто определение находится выше первого и единственного присваивания.
_NN>Вы ведь не будете писать: _NN>Почему с 'using' так не проходит ?
Здравствуйте, AlexRK, Вы писали:
ARK>Здравствуйте, _NN_, Вы писали:
_NN>>Это конечно похоже, но другое. _NN>>Вы предлагаете вариант, где можно изменить значение только один раз, а я говорю о том что проще когда вообще нет возможности поменять значение.
ARK>Нет, я предлагаю вариант, где значение задается только один раз и больше не меняется. Просто определение находится выше первого и единственного присваивания.
Это я понял.
Я не понимаю какой смысл в этом случае ?
Как раз в одном выражение ясно что это и определение и инициализация и не надо искать где и когда устанавливаем значение.
Переменные такого типа нужны, но не в этом случае.
Код может быть запутанным:
A a;
...
if(x)
{
if(y)
{
a = new A();
}
else
{
a = new A(1);
}
}
// И в итоге "a" возможно не проинициализирован ..
// Компилятор конечно хороший и нам подскажет.
А если сразу инициализация то этого просто не может произойти даже по ошибке:
def a =
if(x)
if(y)
new A()
else
new A(1);
// Сразу видим, что не хватает else.
// Ошибка компиляции , мы не дали значение для переменной !
Здравствуйте, samius, Вы писали:
S>А я устал повторять что предлагаю использовать в контрактах записи.
Которые ничего общего с анонимными типами не имеют.
AVK>>Зачем? Если у нас уже есть глобально доступный тип, то проще и короче сослаться на него. S>любой глобально доступный тип может оказаться провайдеру не по силам, т.к. он может иметь нетривиальные геттеры/конструкторы
Какому провайдеру?
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
Здравствуйте, AlexRK, Вы писали:
AVK>>Но это противоречит основополагающим принципам дизайна — менять контракт только потому что поменялись где то очень глубоко внутри детали реализации — это просто фантастическая жесть. ARK>А где они, границы контракта?
В компиляторе.
AVK>>А если учесть, что реализация зависит не от метода Count, а от linq-провайдера, который вообще может динамически вычисляться, то все становится еще фантастичнее. ARK>Ну нагородить можно много чего. В том числе дойти и до динамической типизации. Вопрос, где остановиться.
Что значит остановится? Есть вполне конкретное твое предложение — менять контракт только из-за особенностей реализации где то глубоко внутри.
ARK>Я видел примеры и нахожу их неубедительными.
Находи, тут разговаривать просто не о чем — как тебе неоднократно писали, обсуждать твои нахождения и предположения не интересно, пока ты не сможешь подкрепить их фактами и аргументами.
ARK>Не вижу принципиальной разницы между ARK>
ARK>var a = using(var res = GetRes()) { res.Foo() };
ARK>
ARK>и ARK>
ARK>var a;
ARK>using(var res = GetRes())
ARK>{
ARK> a = res.Foo();
ARK>}
ARK>
А если это лямбда? А если часть сложного выражения? Тоже не видишь?
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, samius, Вы писали:
S>>А я устал повторять что предлагаю использовать в контрактах записи.
AVK>Которые ничего общего с анонимными типами не имеют.
как раз у них все общее, кроме наличия имени.
S>>любой глобально доступный тип может оказаться провайдеру не по силам, т.к. он может иметь нетривиальные геттеры/конструкторы
AVK>Какому провайдеру?
Linq2Sql, например.
Здравствуйте, samius, Вы писали:
AVK>>Которые ничего общего с анонимными типами не имеют. S>как раз у них все общее, кроме наличия имени.
Мне, честно говоря, надоело ходить по кругу:
Ключевая особенность анонимных типов — вывод типа по использованию.
S>>>любой глобально доступный тип может оказаться провайдеру не по силам, т.к. он может иметь нетривиальные геттеры/конструкторы AVK>>Какому провайдеру? S>Linq2Sql, например.
Ему не нужно никаких специальных знаний об анонимном типе, он обрабатывает их по тем же правилам, что и любые другие.
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, samius, Вы писали:
AVK>>>Которые ничего общего с анонимными типами не имеют. S>>как раз у них все общее, кроме наличия имени.
AVK>Мне, честно говоря, надоело ходить по кругу: AVK>
AVK>Ключевая особенность анонимных типов — вывод типа по использованию.
Мне тоже
Одна из особенностей записей (F#) — The compiler infers the type from the labels used (if the labels are sufficiently distinct from those of other record types).
AVK>>>Какому провайдеру? S>>Linq2Sql, например.
AVK>Ему не нужно никаких специальных знаний об анонимном типе, он обрабатывает их по тем же правилам, что и любые другие.
Естественно. Правила для типов одни, и то что работает для анонимного типа, может не сработать для рукописного типа.
Здравствуйте, samius, Вы писали:
S>Одна из особенностей записей (F#)
И что? При чем тут F#?
AVK>>Ему не нужно никаких специальных знаний об анонимном типе, он обрабатывает их по тем же правилам, что и любые другие. S>Естественно. Правила для типов одни, и то что работает для анонимного типа, может не сработать для рукописного типа.
Например?
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, samius, Вы писали:
S>>Одна из особенностей записей (F#)
AVK>И что? При чем тут F#?
Ладно, проехали. Действительно, чего круги нарезать?
AVK>>>Ему не нужно никаких специальных знаний об анонимном типе, он обрабатывает их по тем же правилам, что и любые другие. S>>Естественно. Правила для типов одни, и то что работает для анонимного типа, может не сработать для рукописного типа.
AVK>Например?
Исключение в конструкторе/аксессоре
Ты пока не показал ни одного примера, в котором осмысленное использование оператора как выражения создает какие-то проблемы. Прошу учесть этот момент и продолжать дискуссию только с явным пониманием против чего ты борешься и не является ли твое лекарство хуже предполагаемой болезни.
Z>>Как раз этот подход вполне заменяется экстеншен методами для IEnumarable.
ARK>if/switch тоже заменяются методами. Да и все остальное тоже можно заменить методами.
С какой целью? Экстеншен методы для IEnumarable уже есть и прекрасно работают, что даст замена их на тело цикла из агрегата, что бы это не значило? Switch в виде метода это кошмар, который можно предложить только из желания поспорить и отстоять свое, "оригинальное" мнение.
Z>>Тут очень сложный вопрос, например db.Table1.Count() это функция с побочными эффектами? ARK>Да. По моему мнению (с которым, конечно, согласятся не все), она должна быть в виде процедуры: db.Table1.GetCount(out count)
Все зависит от реализации. Ничто мне не мешает функцию, которая выглядит чистой сделать нечистой, это лишь вопрос культуры кода.
ARK>Это все вкусовщина и имхо. Я вот не понимаю, почему код должен становиться читабельнее и алгоритм пониматься быстрее. Я считаю, что неконтролируемые побочные эффекты ухудшают понимание алгоритма и скрывают потенциальные ошибки (а подход "все есть выражение" этому сильно способствует).
Именно, а использование иммутабельных переменных уменьшает количество требуемых неконтролируемых побочных эффектов. Изменение переменной это само по себе побочный эффект. С другой стороны непонятно, какое отношение побочные эффекты имеют к операторам-выражениям. Больше чем сейчас возможностей для извращенного применения побочных эффектов мы не получаем.
ARK>К примеру, вот тут (слегка измененный пример) ARK>
ARK> var y = src.Any(i => using(var rc = GetDisposableResource()) rc.Foo(i));
ARK>
ARK>при нахождении первого true остальные элементы перебираться не будут и не будут вызваны методы Foo, которые должны выполнить какой-то ввод-вывод.
Вероятно это и нужно программисту. Даже если не нужно, это произошло явно не потому, что там using использовали не так, как тебе привычно.
ARK>Иммутабельные переменные вообще ортогональны данному подходу, их можно с успехом применять и во всех других случаях (на всякий пожарный уточняю, что иммутабельная переменная не обязана быть иниициализированной в точке объявления).
Вообще-то обязательно, по крайней мере в тех языках, которые их умеют. Контроль того, что переменная будет гарантировано инициализирована до использования и инициализирована не более одного раза, доставит программисту немало хлопот. Если перестать придумывать воркэраунд для частного примера с using, это легко увидеть (да, я знаю, что это можно ловить автоматом). Ты предлагаешь жуткие костыли, непонятно с какой целью. Эти костыли никак не помогут справиться с пресловутыми побочными эффектами.
Z>>Можно конечно, только зачем? Мы решим эту локальную проблему ценой снижения читабельности кода. ARK>Опять вкусовщина без обоснования.
Надо обосновать, что разделение места объявления и инициализации переменной снижают читабельность кода? Мне лень искать пруфы, но это азбучная истина.
Ладно, ОК. Я принял к сведению все точки зрения относительно обсуждаемого вопроса. С чем-то могу согласиться, с чем-то нет. Дальше оффтопить, думаю, нет смысла.
Здравствуйте, samius, Вы писали:
AVK>>>>Ему не нужно никаких специальных знаний об анонимном типе, он обрабатывает их по тем же правилам, что и любые другие. S>>>Естественно. Правила для типов одни, и то что работает для анонимного типа, может не сработать для рукописного типа. AVK>>Например? S>Исключение в конструкторе/аксессоре
И в чем хаключается разница в случае linq2sql?
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, samius, Вы писали:
S>>>>Естественно. Правила для типов одни, и то что работает для анонимного типа, может не сработать для рукописного типа. AVK>>>Например? S>>Исключение в конструкторе/аксессоре
AVK>И в чем хаключается разница в случае linq2sql?
Я тут особым образом не выделяю linq2sql. Исключение в конструкторе может нарушить проекцию при работе любого провайдера.
Зря, наверное, сделал акцент на работе провайдеров. Тут больше значимо то, что в описании анонимного типа ошибиться невозможно. У него из коробки все написано корректно. На уровне постулата можно принять то что конструктор не путает поля и не оставляет их непроинициализированными (переданными значениями), плюс заведомо рабочие Equals/GetHashCode/ToString (а могли бы быть еще и ==/!=).
Ручное описание типа, эквивалентного по поведению анонимному — нетривиальная задача. Потому и хочется иметь возможность тривиально описывать такой тип вплоть до совместимости такого явного описания и неявного (по использованию).
Впрочем, совместимость с неявным описанием по использованию — это уже каприз.
Здравствуйте, samius, Вы писали:
S>На уровне постулата можно принять то что конструктор не путает поля и не оставляет их непроинициализированными (переданными значениями), плюс заведомо рабочие Equals/GetHashCode/ToString (а могли бы быть еще и ==/!=).
Нельзя. Потому что в expression tree нет отдельной ноды для анонимного типа, там обычный вызов обычного конструктора. Нет, можно конечно проанализировать CtorInfo и по какому нибудь хитрому признаку догадаться, что это анонимный тип, но вряд ли делать так — разумная идея.
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
Здравствуйте, AndrewVK, Вы писали:
AVK>Нельзя. Потому что в expression tree нет отдельной ноды для анонимного типа, там обычный вызов обычного конструктора. Нет, можно конечно проанализировать CtorInfo и по какому нибудь хитрому признаку догадаться, что это анонимный тип, но вряд ли делать так — разумная идея.
Разумно сделать поддержку анонимных типов в expression tree.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.