Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify Fold Implementation #961

Merged
merged 13 commits into from
Feb 26, 2023
64 changes: 2 additions & 62 deletions MoreLinq/Fold.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,73 +22,13 @@ namespace MoreLinq

static partial class MoreEnumerable
{
static TResult FoldImpl<T, TResult>(IEnumerable<T> source, int count,
Func<T, TResult>? folder1 = null,
Func<T, T, TResult>? folder2 = null,
Func<T, T, T, TResult>? folder3 = null,
Func<T, T, T, T, TResult>? folder4 = null,
Func<T, T, T, T, T, TResult>? folder5 = null,
Func<T, T, T, T, T, T, TResult>? folder6 = null,
Func<T, T, T, T, T, T, T, TResult>? folder7 = null,
Func<T, T, T, T, T, T, T, T, TResult>? folder8 = null,
Func<T, T, T, T, T, T, T, T, T, TResult>? folder9 = null,
Func<T, T, T, T, T, T, T, T, T, T, TResult>? folder10 = null,
Func<T, T, T, T, T, T, T, T, T, T, T, TResult>? folder11 = null,
Func<T, T, T, T, T, T, T, T, T, T, T, T, TResult>? folder12 = null,
Func<T, T, T, T, T, T, T, T, T, T, T, T, T, TResult>? folder13 = null,
Func<T, T, T, T, T, T, T, T, T, T, T, T, T, T, TResult>? folder14 = null,
Func<T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, TResult>? folder15 = null,
Func<T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, TResult>? folder16 = null
)
static T[] Fold<T>(this IEnumerable<T> source, int count)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if ( count == 1 && folder1 == null
|| count == 2 && folder2 == null
|| count == 3 && folder3 == null
|| count == 4 && folder4 == null
|| count == 5 && folder5 == null
|| count == 6 && folder6 == null
|| count == 7 && folder7 == null
|| count == 8 && folder8 == null
|| count == 9 && folder9 == null
|| count == 10 && folder10 == null
|| count == 11 && folder11 == null
|| count == 12 && folder12 == null
|| count == 13 && folder13 == null
|| count == 14 && folder14 == null
|| count == 15 && folder15 == null
|| count == 16 && folder16 == null
)
{ // ReSharper disable NotResolvedInText
#pragma warning disable CA2208 // Instantiate argument exceptions correctly
throw new ArgumentNullException("folder"); // ReSharper restore NotResolvedInText
#pragma warning restore CA2208 // Instantiate argument exceptions correctly
}

var elements = new T[count];
foreach (var e in AssertCountImpl(source.Index(), count, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

return count switch
{
1 => Assume.NotNull(folder1 )(elements[0]),
2 => Assume.NotNull(folder2 )(elements[0], elements[1]),
3 => Assume.NotNull(folder3 )(elements[0], elements[1], elements[2]),
4 => Assume.NotNull(folder4 )(elements[0], elements[1], elements[2], elements[3]),
5 => Assume.NotNull(folder5 )(elements[0], elements[1], elements[2], elements[3], elements[4]),
6 => Assume.NotNull(folder6 )(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5]),
7 => Assume.NotNull(folder7 )(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6]),
8 => Assume.NotNull(folder8 )(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7]),
9 => Assume.NotNull(folder9 )(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8]),
10 => Assume.NotNull(folder10)(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9]),
11 => Assume.NotNull(folder11)(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10]),
12 => Assume.NotNull(folder12)(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11]),
13 => Assume.NotNull(folder13)(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11], elements[12]),
14 => Assume.NotNull(folder14)(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11], elements[12], elements[13]),
15 => Assume.NotNull(folder15)(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11], elements[12], elements[13], elements[14]),
16 => Assume.NotNull(folder16)(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11], elements[12], elements[13], elements[14], elements[15]),
_ => throw new NotSupportedException()
};
return elements;
}

static readonly Func<int, int, Exception> OnFolderSourceSizeErrorSelector = OnFolderSourceSizeError;
Expand Down
96 changes: 80 additions & 16 deletions MoreLinq/Fold.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ partial class MoreEnumerable

public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, TResult> folder)
{
return FoldImpl(source, 1, folder1: folder);
if (source == null) throw new ArgumentNullException(nameof(source));
if (folder == null) throw new ArgumentNullException(nameof(folder));

var elements = source.Fold(1);
return folder(elements[0]);
}

/// <summary>
Expand All @@ -63,7 +67,11 @@ public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, TResu

public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, TResult> folder)
{
return FoldImpl(source, 2, folder2: folder);
if (source == null) throw new ArgumentNullException(nameof(source));
if (folder == null) throw new ArgumentNullException(nameof(folder));

var elements = source.Fold(2);
return folder(elements[0], elements[1]);
}

/// <summary>
Expand All @@ -85,7 +93,11 @@ public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, TR

public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T, TResult> folder)
{
return FoldImpl(source, 3, folder3: folder);
if (source == null) throw new ArgumentNullException(nameof(source));
if (folder == null) throw new ArgumentNullException(nameof(folder));

var elements = source.Fold(3);
return folder(elements[0], elements[1], elements[2]);
}

/// <summary>
Expand All @@ -107,7 +119,11 @@ public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T,

public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T, T, TResult> folder)
{
return FoldImpl(source, 4, folder4: folder);
if (source == null) throw new ArgumentNullException(nameof(source));
if (folder == null) throw new ArgumentNullException(nameof(folder));

var elements = source.Fold(4);
return folder(elements[0], elements[1], elements[2], elements[3]);
}

/// <summary>
Expand All @@ -129,7 +145,11 @@ public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T,

public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T, T, T, TResult> folder)
{
return FoldImpl(source, 5, folder5: folder);
if (source == null) throw new ArgumentNullException(nameof(source));
if (folder == null) throw new ArgumentNullException(nameof(folder));

var elements = source.Fold(5);
return folder(elements[0], elements[1], elements[2], elements[3], elements[4]);
}

/// <summary>
Expand All @@ -151,7 +171,11 @@ public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T,

public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T, T, T, T, TResult> folder)
{
return FoldImpl(source, 6, folder6: folder);
if (source == null) throw new ArgumentNullException(nameof(source));
if (folder == null) throw new ArgumentNullException(nameof(folder));

var elements = source.Fold(6);
return folder(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5]);
}

/// <summary>
Expand All @@ -173,7 +197,11 @@ public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T,

public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, TResult> folder)
{
return FoldImpl(source, 7, folder7: folder);
if (source == null) throw new ArgumentNullException(nameof(source));
if (folder == null) throw new ArgumentNullException(nameof(folder));

var elements = source.Fold(7);
return folder(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6]);
}

/// <summary>
Expand All @@ -195,7 +223,11 @@ public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T,

public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, T, TResult> folder)
{
return FoldImpl(source, 8, folder8: folder);
if (source == null) throw new ArgumentNullException(nameof(source));
if (folder == null) throw new ArgumentNullException(nameof(folder));

var elements = source.Fold(8);
return folder(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7]);
}

/// <summary>
Expand All @@ -217,7 +249,11 @@ public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T,

public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, T, T, TResult> folder)
{
return FoldImpl(source, 9, folder9: folder);
if (source == null) throw new ArgumentNullException(nameof(source));
if (folder == null) throw new ArgumentNullException(nameof(folder));

var elements = source.Fold(9);
return folder(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8]);
}

/// <summary>
Expand All @@ -239,7 +275,11 @@ public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T,

public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, T, T, T, TResult> folder)
{
return FoldImpl(source, 10, folder10: folder);
if (source == null) throw new ArgumentNullException(nameof(source));
if (folder == null) throw new ArgumentNullException(nameof(folder));

var elements = source.Fold(10);
return folder(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9]);
}

/// <summary>
Expand All @@ -261,7 +301,11 @@ public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T,

public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, T, T, T, T, TResult> folder)
{
return FoldImpl(source, 11, folder11: folder);
if (source == null) throw new ArgumentNullException(nameof(source));
if (folder == null) throw new ArgumentNullException(nameof(folder));

var elements = source.Fold(11);
return folder(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10]);
}

/// <summary>
Expand All @@ -283,7 +327,11 @@ public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T,

public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, T, T, T, T, T, TResult> folder)
{
return FoldImpl(source, 12, folder12: folder);
if (source == null) throw new ArgumentNullException(nameof(source));
if (folder == null) throw new ArgumentNullException(nameof(folder));

var elements = source.Fold(12);
return folder(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11]);
}

/// <summary>
Expand All @@ -305,7 +353,11 @@ public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T,

public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, T, T, T, T, T, T, TResult> folder)
{
return FoldImpl(source, 13, folder13: folder);
if (source == null) throw new ArgumentNullException(nameof(source));
if (folder == null) throw new ArgumentNullException(nameof(folder));

var elements = source.Fold(13);
return folder(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11], elements[12]);
}

/// <summary>
Expand All @@ -327,7 +379,11 @@ public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T,

public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, T, T, T, T, T, T, T, TResult> folder)
{
return FoldImpl(source, 14, folder14: folder);
if (source == null) throw new ArgumentNullException(nameof(source));
if (folder == null) throw new ArgumentNullException(nameof(folder));

var elements = source.Fold(14);
return folder(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11], elements[12], elements[13]);
}

/// <summary>
Expand All @@ -349,7 +405,11 @@ public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T,

public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, TResult> folder)
{
return FoldImpl(source, 15, folder15: folder);
if (source == null) throw new ArgumentNullException(nameof(source));
if (folder == null) throw new ArgumentNullException(nameof(folder));

var elements = source.Fold(15);
return folder(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11], elements[12], elements[13], elements[14]);
}

/// <summary>
Expand All @@ -371,7 +431,11 @@ public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T,

public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, TResult> folder)
{
return FoldImpl(source, 16, folder16: folder);
if (source == null) throw new ArgumentNullException(nameof(source));
if (folder == null) throw new ArgumentNullException(nameof(folder));

var elements = source.Fold(16);
return folder(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7], elements[8], elements[9], elements[10], elements[11], elements[12], elements[13], elements[14], elements[15]);
}

}
Expand Down
11 changes: 7 additions & 4 deletions MoreLinq/Fold.g.tt
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,10 @@ namespace MoreLinq
select new
{
Ts = string.Join(", ", Enumerable.Repeat("T", i)),
Count = i,
CountElements = istr + " " + (i == 1 ? "element" : "elements"),
CountArg = istr,
FolderArgs = "folder" + istr + ": folder",

Elements = string.Join(", ", from j in Enumerable.Range(0, i)
select FormattableString.Invariant($"elements[{j}]")),
};

foreach (var e in overloads) { #>
Expand All @@ -61,7 +60,11 @@ namespace MoreLinq

public static TResult Fold<T, TResult>(this IEnumerable<T> source, Func<<#= e.Ts #>, TResult> folder)
{
return FoldImpl(source, <#= e.CountArg #>, <#= e.FolderArgs #>);
viceroypenguin marked this conversation as resolved.
Show resolved Hide resolved
if (source == null) throw new ArgumentNullException(nameof(source));
if (folder == null) throw new ArgumentNullException(nameof(folder));

var elements = source.Fold(<#= e.CountArg #>);
return folder(<#= e.Elements #>);
}

<# } #>
Expand Down