Func に対する拡張メソッド
汎用デリゲート Func に対する拡張メソッドを作成しました。
Func<TResult>
Func<T, TResult>
Func<T1, T2, TResult>
Func<T1, T2, T3, TResult>
(省略)
Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult>
.NET 4.0 では最大16個の引数を持つデリゲートが定義されているわけですが、全ての Func に対応したソースコードがネット上に見つからなかったので作成しました。GutHub にアップしてあります。(かなりニッチな内容で、需要はあまりないかもしれませんが)
【GitHub】mxProject/Misc
カリー化
Func<T1, T2, T3, TResult>
をFunc<T1, Func<T2, Func<T3, TResult>>>
に変換します。
カリー化
/// <summary>
/// Converts the specified delegate to a curried delegate.
/// </summary>
/// <typeparam name="T1"></typeparam>
/// <typeparam name="T2"></typeparam>
/// <typeparam name="T3"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="func"></param>
/// <returns></returns>
public static Func<T1, Func<T2, Func<T3, TResult>>> Curry<T1, T2, T3, TResult>(this Func<T1, T2, T3, TResult> func)
{
return arg1 => arg2 => arg3 => func(arg1, arg2, arg3);
}
// 例
internal static DateTime GetDate(int year, short month, byte day)
{
return new DateTime(year, month, day);
}
Func<int, short, byte, DateTime> f = GetDate;
Func<int, Func<short, Func<byte, DateTime>>> curry = f.Curry();
var result1 = GetDate(2018, 2, 28);
var result2 = curry(2018)(2)(28);
カリー化の解除
Func<T1, Func<T2, Func<T3, TResult>>>
をFunc<T1, T2, T3, TResult>
に変換します。
カリー化の解除
/// <summary>
/// Converts the specified curried delegate to a uncurried delegate.
/// </summary>
/// <typeparam name="T1"></typeparam>
/// <typeparam name="T2"></typeparam>
/// <typeparam name="T3"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="func"></param>
/// <returns></returns>
public static Func<T1, T2, T3, TResult> Uncurry<T1, T2, T3, TResult>(this Func<T1, Func<T2, Func<T3, TResult>>> func)
{
return (arg1, arg2, arg3) => func(arg1)(arg2)(arg3);
}
// 例
internal static DateTime GetDate(int year, short month, byte day)
{
return new DateTime(year, month, day);
}
Func<int, short, byte, DateTime> f = GetDate;
Func<int, Func<short, Func<byte, DateTime>>> curry = f.Curry();
Func<int, short, byte, DateTime> uncurry = curry.Uncrry();
var result1 = curry(2018)(2)(28);
var result2 = uncurry(2018, 2, 28);
遅延評価
引数を与えてFunc<T1, T2, T3, TResult>
をFunc<TResult>
に変換します。引数を与えるだけで実行はされません。
遅延評価
/// <summary>
/// Converts the specified delegate to a lasy evaluation delegate.
/// </summary>
/// <typeparam name="T1"></typeparam>
/// <typeparam name="T2"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="func"></param>
/// <param name="arg1"></param>
/// <param name="arg2"></param>
/// <returns></returns>
public static Func<TResult> Lazy<T1, T2, TResult>(this Func<T1, T2, TResult> func, T1 arg1, T2 arg2)
{
return () => func(arg1, arg2);
}
// 例
internal static DateTime GetDate(int year, short month, byte day)
{
return new DateTime(year, month, day);
}
Func<int, short, byte, DateTime> f = GetDate;
Func<DateTime> lazy = f.Lazy(2018, 2, 28);
var result1 = GetDate(2018, 2, 28);
var result2 = lazy();
部分適用
先頭の引数を与えてFunc<T1, T2, T3, TResult>
をFunc<T2, T3, TResult>
に変換します。引数を与えるだけで実行はされません。
部分適用
/// <summary>
/// Converts the specified delegate to a partial apply delegate.
/// </summary>
/// <typeparam name="T1"></typeparam>
/// <typeparam name="T2"></typeparam>
/// <typeparam name="T3"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="func"></param>
/// <param name="arg1"></param>
/// <returns></returns>
public static Func<T2, T3, TResult> Partial<T1, T2, T3, TResult>(this Func<T1, T2, T3, TResult> func, T1 arg1)
{
return (arg2, arg3) => func(arg1, arg2, arg3);
}
// 例
internal static DateTime GetDate(int year, short month, byte day)
{
return new DateTime(year, month, day);
}
Func<int, short, byte, DateTime> f = GetDate;
Func<short, byte, DateTime> applyYear = f.Partial(2018);
var result1 = GetDate(2018, 2, 28);
var result2 = applyYear(2, 28);
カリー化後の部分適用
Func<T1, Func<T2, Func<T3, TResult>>>
に対して何れかの引数を与えて型引数の数を減らします。カリー化解除と共に使うことが多いのではないかと思います。
カリー化後の部分適用
/// <summary>
/// Converts the specified curried delegate to a partial apply delegate.
/// </summary>
/// <typeparam name="T1"></typeparam>
/// <typeparam name="T2"></typeparam>
/// <typeparam name="T3"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="func"></param>
/// <returns></returns>
public static Func<T2, Func<T3, Func<T1, TResult>>> Partial<T1, T2, T3, TResult>(this Func<T1, Func<T2, Func<T3, TResult>>> func)
{
return arg2 => arg3 => arg1 => func(arg1)(arg2)(arg3);
}
// 例
internal static DateTime GetDate(int year, short month, byte day)
{
return new DateTime(year, month, day);
}
Func<int, short, byte, DateTime> f = GetDate;
Func<int, Func<short, Func<byte, DateTime>>> curry = f.Curry();
Func<int, Func<short, DateTime>> applyDay = curry.Partial().Partial()(28);
Func<int, short, DateTime> applyDayUncurry = applyDay.Uncurry();
var result1 = GetDate(2018, 2, 28);
var result2 = applyDay(2018)(2);
var result3 = applyDayUncurry(2018, 2);