Skip to content

Commit

Permalink
Simplify "Fold" implementation
Browse files Browse the repository at this point in the history
Co-authored-by: Atif Aziz <[email protected]>
  • Loading branch information
viceroypenguin and atifaziz authored Feb 26, 2023
1 parent 0addfbd commit 76c37b3
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 82 deletions.
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 #>);
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

0 comments on commit 76c37b3

Please sign in to comment.