Re[28]: C# 6.0
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.12.13 23:56
Оценка:
Здравствуйте, AndrewVK, Вы писали:

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


S>>Согласен. А можем мы в пределах хотя бы сборки считать MyClass и <A int, B string> синонимами? А в сборках, ссылающихся на сборку, где объявлен MyClass, при наличии соответствующей using директивы?


AVK>Слишком кучеряво, имхо.

Что я должен на это ответить? Что не слишком, имхо?

AVK>>>Можно извне передать проекцию в анонимный тип и предикат для этого анонимного типа.

S>>Это интересно. Linq2Sql скушает запрос с такой проекцией?

AVK>Это основной сценарий применения анонимных типов в линке.


S>>Беда тут в том, что как только мы в запросе воспользуемся этой проекцией, мы получим тип T, чьи свойства мы не знаем.


AVK>Опять я перестаю тебя понимать. Там где мы анонимный тип конструируем, в том методе все его свойства мы знаем. А в других методах работать с типом, который выводится из использования в чужом коде — довольно странная идея.

Ну вот, мы передали в метод, где конструируем Linq запрос, проекцию, строящую анонимный тип. Это значит что метод, конструирующий Linq запрос уже не может пользоваться свойствами анонимного типа. Ибо это странно, хоть и основной сценарий применения анонимных типов в линке.

AVK>>>А в метаданных чего будет?


AVK>При чем тут атрибуты? Ты вытаскиваешь свой хитрый тип в контракты, значит он должен присутствовать в метаданных. Если ничего не делать, то одинаковые в рантайме типы в метаданных будут разными.

да, проблема с этим есть. Но я уже написал что подмена типов не кажется мне отличной идеей.
Re[28]: C# 6.0
От: samius Япония http://sams-tricks.blogspot.com
Дата: 30.12.13 00:03
Оценка:
Здравствуйте, AndrewVK, Вы писали:

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


S>>Само по себе это хорошо, но будет ли это совместимо с анонимными типами?


AVK>В каком смысле совместимо? Если ты нормальный тип задекларировал анонимныей уже не нужен.

В смысле смогу ли я создавать экземпляры черех new {A = 5, B = "10"}.
Уже понял что нет.
Я думал что primary constructors — это короткий способ объявить тип со свойствами, как анонимный по использованию. Оказалось что это короткий способ объявить тип с конструктором но без свойств. Т.е. F# records даже не на горизонте.
Re[13]: C# 6.0
От: AlexRK  
Дата: 30.12.13 07:30
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Вот foreach как раз таки выражением можно и не делать.


В свете наличия LINQ — возможно. Я просто показал вариант, который, на мой взгляд, логичен для "foreach в виде выражения".

AVK>Вроде уже показали пример. Можно еще проще:

AVK>
AVK>var x = src.Count(i => try { CanThrowException(i) } catch { defaultValue });
AVK>var y = src.Sum(i => using(var rc = GetDisposableResource()) rc.Foo(i));
AVK>


Ну понятно. Это спотыкается о мое неприятие побочных эффектов в выражениях, но это только мое личное мнение и оно не имеет отношения к C#. Раз язык такое позволяет, то ввести можно. Про возврат значений циклами while/do вопрос по прежнему открыт.
Re[13]: C# 6.0
От: AlexRK  
Дата: 30.12.13 07:49
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>И снова "мне кажется, что все не так". Обоснуй. Выражение от стейтмента сейчас отличается тем, что statement возвращает void, а большинство statements должно возвращать результат последнего выражения.


Ну, если плюнуть на побочные эффекты в выражениях (что я считаю, однако, очень плохим тоном), то можно try/using тоже сделать в форме выражения. Для циклов не знаю, зачем нужно. Разве что для того, чтобы использовать их внутри этих try/using?

Z>Как раз этот подход вполне заменяется экстеншен методами для IEnumarable.


if/switch тоже заменяются методами. Да и все остальное тоже можно заменить методами.

Z>foreach должен возвращать void (либо быть аналогом Select, но это не очень хороший вариант).


Я свою позицию по этому вопросу уже изложил.

Z>Просто ты не хочешь это принимать. Потому команда C# и делает лишь маленький шажок. Вот ты попользуешься и начнешь сам хотеть побольше выражений.


Не думаю.

Z>Тут очень сложный вопрос, например db.Table1.Count() это функция с побочными эффектами?


Да. По моему мнению (с которым, конечно, согласятся не все), она должна быть в виде процедуры: db.Table1.GetCount(out count)

Z>Код читабельнее. Алгоритм понимается быстрее. Иммутабельные переменные не позволяют пропустить место, где переменная "незаметно" меняется.


Это все вкусовщина и имхо. Я вот не понимаю, почему код должен становиться читабельнее и алгоритм пониматься быстрее. Я считаю, что неконтролируемые побочные эффекты ухудшают понимание алгоритма и скрывают потенциальные ошибки (а подход "все есть выражение" этому сильно способствует).

К примеру, вот тут (слегка измененный пример)
  var y = src.Any(i => using(var rc = GetDisposableResource()) rc.Foo(i));

при нахождении первого true остальные элементы перебираться не будут и не будут вызваны методы Foo, которые должны выполнить какой-то ввод-вывод.

Вот с измеряемыми показателями согласиться могу, например наподобие того, о чем говорил samius — что вместо двух функций для Func и Action будет одна.

Иммутабельные переменные вообще ортогональны данному подходу, их можно с успехом применять и во всех других случаях (на всякий пожарный уточняю, что иммутабельная переменная не обязана быть иниициализированной в точке объявления).

Z>Можно конечно, только зачем? Мы решим эту локальную проблему ценой снижения читабельности кода.


Опять вкусовщина без обоснования.
Re[29]: C# 6.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.12.13 10:50
Оценка:
Здравствуйте, samius, Вы писали:

S>Что я должен на это ответить? Что не слишком, имхо?


Да ничего не должен. Я просто свое мнение высказываю.

AVK>>Опять я перестаю тебя понимать. Там где мы анонимный тип конструируем, в том методе все его свойства мы знаем. А в других методах работать с типом, который выводится из использования в чужом коде — довольно странная идея.

S>Ну вот, мы передали в метод, где конструируем Linq запрос, проекцию, строящую анонимный тип. Это значит что метод, конструирующий Linq запрос уже не может пользоваться свойствами анонимного типа.

Он не может это делать логически, потому что на момент его написания ничего не известно об этом типе. А чтобы стало известно, надо тип явно описать в параметрах метода. А, знеачит, он оказывается в контрактах. Вот и получается, что, вне зависимости от реальных возможностей анонимных типов, их использование таким манером — крайне сомнительная практика.
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[14]: C# 6.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.12.13 10:50
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>В свете наличия LINQ — возможно.


В любом свете. У Липперта был пост в блоге, где он объяснял, почему в стандатной библиотеке нет метода Foreach. Почти все что там написано касается и возврата значения оператором цикла.

AVK>>Вроде уже показали пример. Можно еще проще:

AVK>>
AVK>>var x = src.Count(i => try { CanThrowException(i) } catch { defaultValue });
AVK>>var y = src.Sum(i => using(var rc = GetDisposableResource()) rc.Foo(i));
AVK>>


ARK>Ну понятно. Это спотыкается о мое неприятие побочных эффектов в выражениях


В этих выражениях, в общем случае, нет побочных эффектов.

ARK>Про возврат значений циклами while/do вопрос по прежнему открыт.


Все что я писал про foreach касается всех циклов.
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[14]: C# 6.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.12.13 10:50
Оценка:
Здравствуйте, AlexRK, Вы писали:

Z>>Тут очень сложный вопрос, например db.Table1.Count() это функция с побочными эффектами?

ARK>Да. По моему мнению (с которым, конечно, согласятся не все)

Это не вопрос твоего мнения, это наблюдаемый факт — Count это чистая функция.

Z>>Код читабельнее. Алгоритм понимается быстрее. Иммутабельные переменные не позволяют пропустить место, где переменная "незаметно" меняется.

ARK>Это все вкусовщина и имхо.

Нет. Это тоже наблюдаемый факт — иммутабельный код читается легче и приводит к меньшему количеству ошибок.
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[30]: C# 6.0
От: samius Япония http://sams-tricks.blogspot.com
Дата: 30.12.13 11:03
Оценка:
Здравствуйте, AndrewVK, Вы писали:

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


AVK>Он не может это делать логически, потому что на момент его написания ничего не известно об этом типе. А чтобы стало известно, надо тип явно описать в параметрах метода. А, знеачит, он оказывается в контрактах. Вот и получается, что, вне зависимости от реальных возможностей анонимных типов, их использование таким манером — крайне сомнительная практика.

Правильно, но только потому что они анонимные. Если анонимные типы приравнять к записям, то сомнительность практики станет сомнительна, ведь тип можно будет указывать в параметрах метода.
Re[31]: C# 6.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.12.13 11:08
Оценка:
Здравствуйте, samius, Вы писали:

S>Если анонимные типы приравнять к записям, то сомнительность практики станет сомнительна


Их недостаточно просто приравнять к записям. Ключевая особенность анонимных типов — вывод типа по использованию. И именно поэтому и возникают логические проблемы.
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[15]: C# 6.0
От: AlexRK  
Дата: 30.12.13 11:08
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>В любом свете. У Липперта был пост в блоге, где он объяснял, почему в стандатной библиотеке нет метода Foreach. Почти все что там написано касается и возврата значения оператором цикла.


Это?
http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx

Ну так этот его пост полностью подтверждает мою точку зрения. Что циклы в виде выражений не нужны.

Однако я бы добавил, что особый подвид foreach имеет право на жизнь в виде выражения, если будет иметь агрегатную функцию вместо тела. Это полностью согласуется с позицией Липперта.

AVK>В этих выражениях, в общем случае, нет побочных эффектов.


Как раз в общем случае есть, мы не знаем, что скрывается за Foo, и следует предположить худшее. C# побочные эффекты никак не контролирует.

AVK>Все что я писал про foreach касается всех циклов.


Просто для foreach можно представить что-то разумное, а для do/while только возврат Void.
Re[15]: C# 6.0
От: AlexRK  
Дата: 30.12.13 11:12
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Это не вопрос твоего мнения, это наблюдаемый факт — Count это чистая функция.


Если речь о стандартном DataTable, оторванном от базы, то естественно, что Count — чистая функция.

Но я так понял по вопросу Ziaw, что он имеет в виду некую "connected" модель, когда Count обращается напрямую к базе, и два последовательных вызова могут дать разные результаты. Вот в таком случае я бы сделал Count процедурой.

AVK>Нет. Это тоже наблюдаемый факт — иммутабельный код читается легче и приводит к меньшему количеству ошибок.


Я говорю не про иммутабельный код, а про подход "все есть выражение". Это вещи, никак не связанные друг с другом.
Против кода с иммутабельными переменными я ничего не имею.
Re[32]: C# 6.0
От: samius Япония http://sams-tricks.blogspot.com
Дата: 30.12.13 11:27
Оценка:
Здравствуйте, AndrewVK, Вы писали:

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


S>>Если анонимные типы приравнять к записям, то сомнительность практики станет сомнительна


AVK>Их недостаточно просто приравнять к записям. Ключевая особенность анонимных типов — вывод типа по использованию. И именно поэтому и возникают логические проблемы.

Хорошо, ключевая особенность анонимных типов порождает проблемы. Какие проблемы порождает предложение слегка их разанонимизировать? Что мешает по использованию вывести тип объявленной ранее записи?
Re[33]: C# 6.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.12.13 11:40
Оценка:
Здравствуйте, samius, Вы писали:

S>Хорошо, ключевая особенность анонимных типов порождает проблемы. Какие проблемы порождает предложение слегка их разанонимизировать?


Я уже устал повторять одно и тоже — использование в контрактах выводимых по использованию типов это порождает.

S> Что мешает по использованию вывести тип объявленной ранее записи?


Зачем? Если у нас уже есть глобально доступный тип, то проще и короче сослаться на него.
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[16]: C# 6.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.12.13 11:40
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Ну так этот его пост полностью подтверждает мою точку зрения. Что циклы в виде выражений не нужны.


Ты тоже не читаешь ответы собеседников? Я тебе уже несколько раз написал тоже самое.

ARK>Однако я бы добавил, что особый подвид foreach имеет право на жизнь в виде выражения, если будет иметь агрегатную функцию вместо тела.


А зачем он нужен?

AVK>>В этих выражениях, в общем случае, нет побочных эффектов.

ARK>Как раз в общем случае есть, мы не знаем, что скрывается за Foo, и следует предположить худшее. C# побочные эффекты никак не контролирует.

Это другой вопрос. Главное — сами операторы никаких побочных эффектов не содержат и нет никаких препятствий сделать их возвращающими значение.
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[16]: C# 6.0
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.12.13 11:40
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Но я так понял по вопросу Ziaw, что он имеет в виду некую "connected" модель, когда Count обращается напрямую к базе, и два последовательных вызова могут дать разные результаты. Вот в таком случае я бы сделал Count процедурой.


Что ты бы сделал мы уже поняли. Но это противоречит основополагающим принципам дизайна — менять контракт только потому что поменялись где то очень глубоко внутри детали реализации — это просто фантастическая жесть. А если учесть, что реализация зависит не от метода Count, а от linq-провайдера, который вообще может динамически вычисляться, то все становится еще фантастичнее.

AVK>>Нет. Это тоже наблюдаемый факт — иммутабельный код читается легче и приводит к меньшему количеству ошибок.

ARK>Я говорю не про иммутабельный код, а про подход "все есть выражение". Это вещи, никак не связанные друг с другом.

Это вещи сильно связанные друг с другом. Примеры тебе уже приводили.
... << RSDN@Home 1.2.0 alpha 5 rev. 100 on Windows 8 6.2.9200.0>>
AVK Blog
Re[17]: C# 6.0
От: AlexRK  
Дата: 30.12.13 12:15
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Ты тоже не читаешь ответы собеседников? Я тебе уже несколько раз написал тоже самое.


Как раз-таки я читаю ответы, а вы — нет.

Я с самого начала написал:

Цикл — выражение? Ну это же тупо.

В принципе, foreach может быть выражением, если у него вместо тела будет предикат типа "all", "any", "max", "min" и т.п. Это грамотный подход. А "выражение, возвращающее ничто" это какая-то хрень.


На что вы дали не вполне уместные ответы:

Вот foreach как раз таки выражением можно и не делать.

Все что я писал про foreach касается всех циклов.


AVK>А зачем он нужен?


Для удобства. Затем же, зачем query comprehension.

AVK>Это другой вопрос. Главное — сами операторы никаких побочных эффектов не содержат и нет никаких препятствий сделать их возвращающими значение.


Просто эти операторы в некоторых случаях способствуют появлению ошибок, связанных с побочными эффектами (пример я приводил выше).
Re[17]: C# 6.0
От: AlexRK  
Дата: 30.12.13 12:22
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Но это противоречит основополагающим принципам дизайна — менять контракт только потому что поменялись где то очень глубоко внутри детали реализации — это просто фантастическая жесть.


А где они, границы контракта? Почему нет претензий к Count, ведь он возвращает Int32, а вдруг в глубине реализации появилось нечто, возвращающее Int64?
Как обычно — баланс между надежностью и гибкостью. Четкое разделение на чистые/нечистые функции увеличивает предсказуемость, но снижает гибкость.

AVK>А если учесть, что реализация зависит не от метода Count, а от linq-провайдера, который вообще может динамически вычисляться, то все становится еще фантастичнее.


Ну нагородить можно много чего. В том числе дойти и до динамической типизации. Вопрос, где остановиться.

AVK>Это вещи сильно связанные друг с другом. Примеры тебе уже приводили.


Я видел примеры и нахожу их неубедительными.
Не вижу принципиальной разницы между
var a = using(var res = GetRes()) { res.Foo() };

и
var a;
using(var res = GetRes())
{
  a = res.Foo();
}
Re[18]: C# 6.0
От: _NN_ www.nemerleweb.com
Дата: 30.12.13 12:47
Оценка:
Здравствуйте, AlexRK, Вы писали:


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>


Разница будет если вместо 'var' будет что-то в стиле 'readonly var' a.k.a 'let', 'def', 'val' и т.п.
Т.е. переменная гарантированно не будет никогда изменяться больше.
В этом случае мы видим одно и единственное место где происходит инициализация.
А обычный 'var' означает, что дальше запросто может быть код вида "a = null;" .
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[34]: C# 6.0
От: samius Япония http://sams-tricks.blogspot.com
Дата: 30.12.13 12:53
Оценка:
Здравствуйте, AndrewVK, Вы писали:

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


S>>Хорошо, ключевая особенность анонимных типов порождает проблемы. Какие проблемы порождает предложение слегка их разанонимизировать?


AVK>Я уже устал повторять одно и тоже — использование в контрактах выводимых по использованию типов это порождает.

А я устал повторять что предлагаю использовать в контрактах записи. Но для этого они хотя бы должны быть.

S>> Что мешает по использованию вывести тип объявленной ранее записи?


AVK>Зачем? Если у нас уже есть глобально доступный тип, то проще и короче сослаться на него.

любой глобально доступный тип может оказаться провайдеру не по силам, т.к. он может иметь нетривиальные геттеры/конструкторы. Нужен именно аналог анонимного типа с именем, т.е. запись.
Re[19]: C# 6.0
От: AlexRK  
Дата: 30.12.13 12:55
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Разница будет если вместо 'var' будет что-то в стиле 'readonly var' a.k.a 'let', 'def', 'val' и т.п.

_NN>Т.е. переменная гарантированно не будет никогда изменяться больше.
_NN>В этом случае мы видим одно и единственное место где происходит инициализация.
_NN>А обычный 'var' означает, что дальше запросто может быть код вида "a = null;" .

Абсолютно никакой разницы. В случае def/let будет то же самое. А если человек попробует после "def a" написать "a = null;" — ошибка компиляции.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.