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
70 changes: 0 additions & 70 deletions MoreLinq/Fold.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,79 +18,9 @@
namespace MoreLinq
{
using System;
using System.Collections.Generic;

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
)
{
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()
};
}

static readonly Func<int, int, Exception> OnFolderSourceSizeErrorSelector = OnFolderSourceSizeError;

static Exception OnFolderSourceSizeError(int cmp, int count) =>
Expand Down
144 changes: 128 additions & 16 deletions MoreLinq/Fold.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,14 @@ 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 = new T[1];
foreach (var e in AssertCountImpl(source.Index(), 1, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

return folder(elements[0]);
}

/// <summary>
Expand All @@ -63,7 +70,14 @@ 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 = new T[2];
foreach (var e in AssertCountImpl(source.Index(), 2, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

return folder(elements[0], elements[1]);
}

/// <summary>
Expand All @@ -85,7 +99,14 @@ 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 = new T[3];
foreach (var e in AssertCountImpl(source.Index(), 3, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

return folder(elements[0], elements[1], elements[2]);
}

/// <summary>
Expand All @@ -107,7 +128,14 @@ 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 = new T[4];
foreach (var e in AssertCountImpl(source.Index(), 4, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

return folder(elements[0], elements[1], elements[2], elements[3]);
}

/// <summary>
Expand All @@ -129,7 +157,14 @@ 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 = new T[5];
foreach (var e in AssertCountImpl(source.Index(), 5, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

return folder(elements[0], elements[1], elements[2], elements[3], elements[4]);
}

/// <summary>
Expand All @@ -151,7 +186,14 @@ 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 = new T[6];
foreach (var e in AssertCountImpl(source.Index(), 6, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

return folder(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5]);
}

/// <summary>
Expand All @@ -173,7 +215,14 @@ 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 = new T[7];
foreach (var e in AssertCountImpl(source.Index(), 7, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

return folder(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6]);
}

/// <summary>
Expand All @@ -195,7 +244,14 @@ 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 = new T[8];
foreach (var e in AssertCountImpl(source.Index(), 8, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

return folder(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5], elements[6], elements[7]);
}

/// <summary>
Expand All @@ -217,7 +273,14 @@ 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 = new T[9];
foreach (var e in AssertCountImpl(source.Index(), 9, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

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 +302,14 @@ 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 = new T[10];
foreach (var e in AssertCountImpl(source.Index(), 10, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

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 +331,14 @@ 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 = new T[11];
foreach (var e in AssertCountImpl(source.Index(), 11, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

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 +360,14 @@ 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 = new T[12];
foreach (var e in AssertCountImpl(source.Index(), 12, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

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 +389,14 @@ 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 = new T[13];
foreach (var e in AssertCountImpl(source.Index(), 13, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

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 +418,14 @@ 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 = new T[14];
foreach (var e in AssertCountImpl(source.Index(), 14, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

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 +447,14 @@ 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 = new T[15];
foreach (var e in AssertCountImpl(source.Index(), 15, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

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 +476,14 @@ 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 = new T[16];
foreach (var e in AssertCountImpl(source.Index(), 16, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

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
13 changes: 10 additions & 3 deletions MoreLinq/Fold.g.tt
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ namespace MoreLinq
Count = i,
CountElements = istr + " " + (i == 1 ? "element" : "elements"),
CountArg = istr,
FolderArgs = "folder" + istr + ": folder",

Elements = string.Join(", ", Enumerable.Range(0, i)
.Select(j => FormattableString.Invariant($"elements[{j}]"))),
atifaziz marked this conversation as resolved.
Show resolved Hide resolved
};

foreach (var e in overloads) { #>
Expand All @@ -61,7 +61,14 @@ 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 = new T[<#= e.Count #>];
foreach (var e in AssertCountImpl(source.Index(), <#= e.Count #>, OnFolderSourceSizeErrorSelector))
elements[e.Key] = e.Value;

atifaziz marked this conversation as resolved.
Show resolved Hide resolved
return folder(<#= e.Elements #>);
}

<# } #>
Expand Down