Расширения общего списка в С#
Я пишу несколько расширений для имитации карты и сокращения функций в Lisp.
public delegate R ReduceFunction<T,R>(T t, R previous);
public delegate void TransformFunction<T>(T t, params object[] args);
public static R Reduce<T,R>(this List<T> list, ReduceFunction<T,R> r, R initial)
{
var aggregate = initial;
foreach(var t in list)
aggregate = r(t,aggregate);
return aggregate;
}
public static void Transform<T>(this List<T> list, TransformFunction<T> f, params object [] args)
{
foreach(var t in list)
f(t,args);
}
Функция преобразования будет сжиматься на крутизне, например:
foreach(var t in list)
if(conditions && moreconditions)
//do work etc
Это имеет смысл? Это может быть лучше?
Ответы
Ответ 1
Они уже очень похожи на расширения в Linq:
//takes a function that matches the Func<T,R> delegate
listInstance.Aggregate(
startingValue,
(x, y) => /* aggregate two subsequent values */ );
//takes a function that matches the Action<T> delegate
listInstance.ForEach(
x => /* do something with x */);
Почему второй пример называется Transform? Вы собираетесь каким-то образом изменить значения в списке? Если в этом случае вам может быть лучше использовать ConvertAll<T>
или Select<T>
.
Ответ 2
В соответствии с этой ссылкой Функциональное программирование на С# 3.0: как Map/Reduce/Filter может сканировать ваш мир, следующие эквиваленты на С# в разделе пространство имен System.Linq:
Ответ 3
Вместо этого я бы использовал встроенные делегаты Func. Этот же код будет работать с любым IEnumerable. Ваш код будет выглядеть следующим образом:
public static R Reduce<T,R>(this IEnumerable<T> list, Func<T,R> r, R initial)
{
var aggregate = initial;
foreach(var t in list)
aggregate = r(t,aggregate);
return aggregate;
}
public static void Transform<T>(this IEnumerable<T> list, Func<T> f)
{
foreach(var t in list)
f(t);
}
Ответ 4
Возможно, вы захотите добавить способ сделать карту, но вернуть новый список, вместо того, чтобы работать с перечнем, переданным (и возврат списка может оказаться полезным для цепочки других операций)... возможно, перегруженная версия с boolean, который указывает, хотите ли вы вернуть новый список или нет, как таковой:
public static List<T> Transform<T>(this List<T> list, TransformFunction<T> f,
params object [] args)
{
return Transform(list, f, false, args);
}
public static List<T> Transform<T>(this List<T> list, TransformFunction<T> f,
bool create, params object [] args)
{
// Add code to create if create is true (sorry,
// too lazy to actually code this up)
foreach(var t in list)
f(t,args);
return list;
}