Re[13]: Давайте поговорим о c# 3.0
От: Undying Россия  
Дата: 27.09.08 18:37
Оценка: :))
Здравствуйте, Mirrorer, Вы писали:

M>Ну например. Возьмем простой пример. Просуммировать список чисел

M>
M>var sum = 0;
M>foreach var x in someList
M>   sum += x
M>


M>Допустим нам понадобилось сделать умножение.

M>И что видно ? Видно дублирование кода. Отличие только в начальном значении суммы и функции, которая будет применяться на каждом шаге.

M>
M>  var sum2 = Accumulate<int, int>(0, (s, x) => s + x);
M>


M>Мы теперь можно чувствовать себя крутым. Мы абсрагировали способ обхода коллекции (foreach) от операций которые будут выполняться на каждом шаге. M>Уберутся ненужные дублирования и т.п.


А в чем заключается убирание дублирования? При императивном подходе мы дважды писали foreach, при функциональном дважды пишем Accumulate. В чем выигрыш?

При этом выучив foreach один раз его можно использовать в миллионе случаев, а Accumulate покрывает куда меньшее количество случаев, соответственно для того, чтобы иметь возможность решить те же задачи, которые решаются с помощью foreach, нужно выучить не только Accumulate, но и еще 125 различных функций.

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

По-своему опыту скажу, что в случае простых преобразований вместо трех строчек с foreach'ем я охотно использую статистическую функцию в тех случаях, когда этой функции не нужно принимать делегат, например: _.Combine<T>(params IEnumerable<T>[] collections). Если функция использует делегат, то чуть большая лаконичность написания, на мой взгляд, не окупает необходимости вспоминать специальную функцию.

Функции же с делегатами я охотно использую только в случае достаточно сложных, но стандартных преобразований, например:

CollectionSynchronizer.Synchronize<TLeft, TRight, TKey>(IEnumerable<TLeft> left, Getter<TKey, TLeft> leftKeyer, IEnumerable<TRight> right, Getter<TKey, TRight>, Executter<TLeft> onlyLeft, Executter<TRight> onlyRight, Executter<TLeft, TRight> both);


Вот в решении подобных стандартных задач функциональному подходу самое место.

ps
Т.е. ни в коем случае нельзя противопоставлять императивный и функциональный подход, подавая функциональщину как серебрянную пулю, которая в скором времени вытеснит императивщину. Главное достоинство C# заключается в том, что он позволяет использовать и тот, и другой подход, выбирая более подходящий для конкретной задачи.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.