Здравствуйте, Воронков Василий, Вы писали:
ВВ>На мой взгляд преимущество тут точно такое же как и у простого Where(x => Condition(x)) перед if (Condition(x)) {} — когда "букаф" даже больше получается.
В отличии от ForEach/foreach они не эквивалентны. Для функцифонального стиля уже есть аналог foreach, это Select(). Все что выходит за рамки селекта почти наверняка будет нести побочные эффекты и придавать этому вид функции означает запутать читателя.
ВВ>Ну и давайте вспомним такую штуку как однообразность кода. Если я в одном месте использую ForEach, то и в другом, в аналогичной ситуации, хотелось бы тоже.
Здравствуйте, Воронков Василий, Вы писали:
IB>>http://blogs.msdn.com/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx
ВВ>Ну и что? Там высказано частное мнение, что ForEach в таком виде это вообще плохо. Основная причина, что противоречит принципам функционального программирования. Я как-то не припомню, чтобы C# стал pure functional language. Лично мне запись вида:
ВВ>list.ForEach(x => DoSmth(x), x => Condition(x));
В таком виде эта запись действительно не нужна — слишком много на себя берёт.
Здравствуйте, Ziaw, Вы писали:
Z>В отличии от ForEach/foreach они не эквивалентны. Для функцифонального стиля уже есть аналог foreach, это Select().
Селект — это не аналог foreach.
Z>Все что выходит за рамки селекта почти наверняка будет нести побочные эффекты и придавать этому вид функции означает запутать читателя.
А причем тут функциональный стиль?
ВВ>>Ну и давайте вспомним такую штуку как однообразность кода. Если я в одном месте использую ForEach, то и в другом, в аналогичной ситуации, хотелось бы тоже. Z>В каком месте?
В одном у меня есть кондишин, в другом — нет.
Вообще я не понимаю, т.е. все отписавшиеся считают, что то, что в этом блоге написано — святая истина и вопрос полностью закрыт? Тут домен блога оказывает какое-то особое воздействие или же просто сам факт, что это блог? Если я заведу блог и напишу, что нельзя использовать Where, потому что:
1. В общем случае код не становится короче (а иногда — даже длиннее)
2. Дебажить неудобно (а как вы будете дебажить Where(x => x == y)?)
и прочее в том же духе.
То вы не будете Where использовать?
Единственный аргумент там — то, что ForEach — это не функционально. Аргумент весьма своеобразный на мой взгляд. Я вот никогда не видел приложение на шарпе написанное целиком функционально. Да и в Линк при желании можно запихать побочных эффектов по самое не могу — и все будет прекрасно работать.
Может, в таком случае выбор языке не совсем правильный?
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, Воронков Василий, Вы писали:
ВВ>>Вообще касательно ForEach я потихоньку пришел к выводу, что не грех самом деле свой ForEach написать. С т.з. лаконичности кода это окупиться сто раз, к тому же часто приходится работать и с коллекциями, которые восходят к не-генерик интерфейсам — и можно сделать универсальную реализацию, которая позволит избежать лишних преобразований.
IB>http://blogs.msdn.com/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx
Мне показалось, что статья объясняет то, "почему Microsoft не предоставила для последовательностей метод расширения ForEach". Среди методов System.Linq.Enumerable.* ForEach действительно смотрелся бы странно.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Ну если оперировать теми же аргументами, что и в приведенном здесь блоге, то этот вариант практически идентичен вышеприведенному — ведь кол-во символов практически то же:
Ну, ты бы хоть по русски прочитал, если в оригинале не очень понятно, тем более, что ссылку уже дали.
Действительно, зря что ли Синклер старался? http://blogs.msdn.com/ruericlippert/archive/2009/05/18/foreach-foreach.aspx
ВВ>Вывод, мне кажется, каждый делает сам..
Угу.
Здравствуйте, _FRED_, Вы писали:
_FR>В таком виде эта запись действительно не нужна — слишком много на себя берёт. _FR>
_FR>list.Where(Condition).ForEach(DoSmth);
_FR>
А можно обосновать этот критерий — "слишком много"?
Применить действие Х по условию Y — вполне нормальная операция на мой взгляд.
Ты меняешь это на две операции:
Выбрать по условию Y
Применить действие Х для выбранного
Два раза бежим по списку — ну да бог с ним. Главное, какое проблема решена в результате? Ни одна из описываемых здесь "проблем" — не решается. И главное —
foreach (var x in list) if (Condition(x)) DoSmth(x);
Здравствуйте, IB, Вы писали:
ВВ>>Ну если оперировать теми же аргументами, что и в приведенном здесь блоге, то этот вариант практически идентичен вышеприведенному — ведь кол-во символов практически то же: IB>Ну, ты бы хоть по русски прочитал, если в оригинале не очень понятно, тем более, что ссылку уже дали.
Спасибо, я читаю по-английски. И никакого "послания" кроме как это "нефукционально" я там не вижу. Все остальные "недостатки" точно также применимы и для Линк.
ВВ>>Вывод, мне кажется, каждый делает сам.. IB>Угу.
Здравствуйте, _FRED_, Вы писали:
_FR>Мне показалось, что статья объясняет то, "почему Microsoft не предоставила для последовательностей метод расширения ForEach". Среди методов System.Linq.Enumerable.* ForEach действительно смотрелся бы странно.
Эти же аргументы подходят и для того, чтобы не делать свой extension ForEach.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Селект — это не аналог foreach.
if -> Where()
точно также как и
foreach -> Select()
ВВ>А причем тут функциональный стиль?
при топике
ВВ>Вообще я не понимаю, т.е. все отписавшиеся считают, что то, что в этом блоге написано — святая истина и вопрос полностью закрыт? Тут домен блога оказывает какое-то особое воздействие или же просто сам факт, что это блог?
То, что это блог Эрика Липперта. Впрочем я не беру на веру все блоги, к данному выводу я пришел сам до чтения.
ВВ>Если я заведу блог и напишу, что нельзя использовать Where, потому что:
ВВ>1. В общем случае код не становится короче (а иногда — даже длиннее) ВВ>2. Дебажить неудобно (а как вы будете дебажить Where(x => x == y)?) ВВ>и прочее в том же духе.
ВВ>То вы не будете Where использовать?
Если предложите аналог заменяющий Where во всех сценариях использования можно будет обсуждать.
ВВ>Единственный аргумент там — то, что ForEach — это не функционально. Аргумент весьма своеобразный на мой взгляд. Я вот никогда не видел приложение на шарпе написанное целиком функционально. Да и в Линк при желании можно запихать побочных эффектов по самое не могу — и все будет прекрасно работать.
А я и не предлагаю писать все предложение функционально, я предлагаю не писать в функциональном стиле императивный код.
Здравствуйте, Воронков Василий, Вы писали:
_FR>>В таком виде эта запись действительно не нужна — слишком много на себя берёт.
_FR>>list.Where(Condition).ForEach(DoSmth);
ВВ>А можно обосновать этот критерий — "слишком много"?
Конечно: SRP, "Разделяй и влавствуй" и прочее и прочее — две функции, каждая из которых решает какую-то одну маленькую задачу лучше чем одна, решающая две две, что первые можно комбинировать. Вот пример — сколько у тебя сейчас перегрузок ForEach? Допустим, две:
Но вот у меня есть ещё варианты ForEach, передающие в Action два параметра — элемент и его индекс. Тебе, что бы этого добиться и поддржать согласованость API придётся добавить две перегрузки:
Здравствуйте, _FRED_, Вы писали:
_FR>Как так "не останется"? Например по guidelines принятым у нас в конторе guidelines вышеприведённый код расползается — угадай, на сколько строк?
foreach (var x in list.Where(Condition))
{
DoSmth(x);
}
Здравствуйте, IB, Вы писали:
_FR>>Мне показалось, что статья объясняет то, "почему Microsoft не предоставила для последовательностей метод расширения ForEach". Среди методов System.Linq.Enumerable.* ForEach действительно смотрелся бы странно. IB>Эти же аргументы подходят и для того, чтобы не делать свой extension ForEach.
Вот первый:
Во-первых, это нарушило бы принципы функционального программирования, на которых основаны все остальные операторы на последовательностях.
foreach как-то вообще не очень совместим с "принципами функционального программирования", так что этот пункт обсуждать неинтересно. Или я не прав?
Во-вторых, такая возможность ничего не добавляет к выразительности языка. Она всего лишь позволяет вам переписать вот этот идеально понятный код… (в другом виде [прим. _FRED_])
Да, позволяет переписать "в другом". А что тут некошерного?
И вторую версию даже труднее понять и отладить, …
В том виде как это показывает Эрик:
foos.ForEach((Foo foo)=>{ какой-то оператор с foo; });
да, но есть же и более простые случаи:
foos.ForEach(DoSmth);
а еще она добавляет семантику замыкания, потенциально внося тонкие изменения в жизненные циклы объектов.
Это так же относится к злоупотреблению. Но со "злоупотреблением" нужно бороться другими методами, такими как рефакторинг, например.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Ziaw, Вы писали:
_FR>>Как так "не останется"? Например по guidelines принятым у нас в конторе guidelines вышеприведённый код расползается — угадай, на сколько строк?
Z>foreach (var x in list.Where(Condition))
Z>{
Z> DoSmth(x);
Z>}
Z>Не очень убеждает.
Расскажи пожалуйста о преимуществах Where в данном конкретном примере над if.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Это так же относится к злоупотреблению. Но со "злоупотреблением" нужно бороться другими методами, такими как рефакторинг, например.
Здесь я имел в виду то, что когда метод в ForEach становится сложным, и читать и отлаживать действительно непросто. Но сложно [плохо] написанный код тяжело поддаётся отладке во многих случаях и не потому что не надо "вредных" методов добавлять, а потому что не нужно сложно писать. А если писать "не сложно", то проблем с отладкой и читабельностью не будет.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Ziaw, Вы писали:
ВВ>>Селект — это не аналог foreach. Z>if -> Where() Z>точно также как и Z>foreach -> Select()
Правда что ли? Как же вы это сравниваете императивные конструкции и функциональными?
ВВ>>А причем тут функциональный стиль? Z>при топике
Ну так перечитайте первое сообщение.
Z>Если предложите аналог заменяющий Where во всех сценариях использования можно будет обсуждать.
foreach
ВВ>>Единственный аргумент там — то, что ForEach — это не функционально. Аргумент весьма своеобразный на мой взгляд. Я вот никогда не видел приложение на шарпе написанное целиком функционально. Да и в Линк при желании можно запихать побочных эффектов по самое не могу — и все будет прекрасно работать. Z>А я и не предлагаю писать все предложение функционально, я предлагаю не писать в функциональном стиле императивный код.
Таким образом мысль блога сводится к тому, что single statement lambda нельзя использовать в тех случаях, когда у нас есть побочные эффекты. Что предлагается взамен? Использовать простые делегаты, анонимные делегаты, заставлять себя вставлять фигурные скобки даже если лямбда состоит из одного выражения? Вывод какой? Или это так — просто потрепаться? Если я напишу:
list.ForEach(x => { DoSmth(x); });
То все, проблема снята? Или лучше вообще:
list.ForEach(delegate(Type x) => { DoSmth(x); });
Никакого функционального стиля, ага?
А теперь смотрим на саму функцию:
Возникает вопрос — а какой именно код написан функционально? Что вы предлагаете не писать в функциональном стиле? Использовать другой синтаксис для передачи колл-беков?
Используйте любой синтаксис, если считаете ввод подобных ограничений разумным. Только вот вопроса с ForEach и foreach это никак не касается.