From 0ec9b4ff6ae88cc3d10efa30ddbdcbed6473d411 Mon Sep 17 00:00:00 2001 From: Phillip Palk Date: Sat, 16 Nov 2019 01:20:45 +1000 Subject: [PATCH 1/4] Added Tuplewise operator --- MoreLinq.Test/MoreLinq.Test.csproj | 13 +++ MoreLinq.Test/TuplewiseTest.g.cs | 86 ++++++++++++++++ MoreLinq.Test/TuplewiseTest.g.tt | 103 +++++++++++++++++++ MoreLinq/Extensions.g.cs | 78 +++++++++++++-- MoreLinq/MoreLinq.csproj | 10 ++ MoreLinq/Pairwise.cs | 31 ++---- MoreLinq/Tuplewise.g.cs | 152 +++++++++++++++++++++++++++++ MoreLinq/Tuplewise.g.tt | 90 +++++++++++++++++ README.md | 6 ++ 9 files changed, 538 insertions(+), 31 deletions(-) create mode 100644 MoreLinq.Test/TuplewiseTest.g.cs create mode 100644 MoreLinq.Test/TuplewiseTest.g.tt create mode 100644 MoreLinq/Tuplewise.g.cs create mode 100644 MoreLinq/Tuplewise.g.tt diff --git a/MoreLinq.Test/MoreLinq.Test.csproj b/MoreLinq.Test/MoreLinq.Test.csproj index ea2da2dde..f5ad90ec4 100644 --- a/MoreLinq.Test/MoreLinq.Test.csproj +++ b/MoreLinq.Test/MoreLinq.Test.csproj @@ -60,6 +60,11 @@ + + True + True + TuplewiseTest.g.tt + @@ -78,7 +83,15 @@ + + + + TextTemplatingFileGenerator + TuplewiseTest.g.cs + + + diff --git a/MoreLinq.Test/TuplewiseTest.g.cs b/MoreLinq.Test/TuplewiseTest.g.cs new file mode 100644 index 000000000..bdb84e273 --- /dev/null +++ b/MoreLinq.Test/TuplewiseTest.g.cs @@ -0,0 +1,86 @@ +#region License and Terms +// MoreLINQ - Extensions to LINQ to Objects +// Copyright (c) 2019 Phillip Palk. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +namespace MoreLinq.Test +{ + using System; + using System.Collections.Generic; + using NUnit.Framework; + + [TestFixture] + public class TuplewiseTest + { + private void TuplewiseNWide(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector, IEnumerable source, params TResult[] fullResult) + { + var arity = resultSelector.GetType().GetGenericArguments().Length - 1; + + for (var i = 0; i < fullResult.Length; ++i) + using (var ts = source.Take(i).AsTestingSequence()) + Assert.That(tuplewise(ts, resultSelector), Is.EqualTo(fullResult.Take(i - arity + 1))); + } + + private void TuplewiseNWideInt(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector) + { + const int rangeLen = 100; + var arity = resultSelector.GetType().GetGenericArguments().Length - 1; + + TuplewiseNWide( + tuplewise, + resultSelector, + Enumerable.Range(1, rangeLen), + Enumerable.Range(1, rangeLen - (arity - 1)).Select(x => x * arity + Enumerable.Range(1, arity - 1).Sum()).ToArray() + ); + } + + private void TuplewiseNWideString(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector) + { + const string alphabet = "abcdefghijklmnopqrstuvwxyz"; + var arity = resultSelector.GetType().GetGenericArguments().Length - 1; + + TuplewiseNWide( + tuplewise, + resultSelector, + alphabet, + Enumerable.Range(0, alphabet.Length - (arity - 1)).Select(i => alphabet.Skip(i).Take(arity)).ToArray() + ); + } + + [Test] + public void TuplewiseIsLazy() + { + new BreakingSequence().Tuplewise(BreakingFunc.Of()); + new BreakingSequence().Tuplewise(BreakingFunc.Of()); + new BreakingSequence().Tuplewise(BreakingFunc.Of()); + } + + [Test] + public void TuplewiseIntegers() + { + TuplewiseNWideInt>((source, func) => MoreEnumerable.Tuplewise(source, func), (a, b ) => a + b ); + TuplewiseNWideInt>((source, func) => MoreEnumerable.Tuplewise(source, func), (a, b, c ) => a + b + c ); + TuplewiseNWideInt>((source, func) => MoreEnumerable.Tuplewise(source, func), (a, b, c, d) => a + b + c + d); + } + + [Test] + public void TuplewiseStrings() + { + TuplewiseNWideString>((source, func) => MoreEnumerable.Tuplewise(source, func), (a, b ) => string.Join(string.Empty, a, b )); + TuplewiseNWideString>((source, func) => MoreEnumerable.Tuplewise(source, func), (a, b, c ) => string.Join(string.Empty, a, b, c )); + TuplewiseNWideString>((source, func) => MoreEnumerable.Tuplewise(source, func), (a, b, c, d) => string.Join(string.Empty, a, b, c, d)); + } + } +} diff --git a/MoreLinq.Test/TuplewiseTest.g.tt b/MoreLinq.Test/TuplewiseTest.g.tt new file mode 100644 index 000000000..8bf12b4bf --- /dev/null +++ b/MoreLinq.Test/TuplewiseTest.g.tt @@ -0,0 +1,103 @@ +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ output extension=".cs" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Globalization" #> +<#@ import namespace="System.Linq" #> +#region License and Terms +// MoreLINQ - Extensions to LINQ to Objects +// Copyright (c) 2019 Phillip Palk. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +namespace MoreLinq.Test +{ + using System; + using System.Collections.Generic; + using NUnit.Framework; + + [TestFixture] + public class TuplewiseTest + { + private void TuplewiseNWide(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector, IEnumerable source, params TResult[] fullResult) + { + var arity = resultSelector.GetType().GetGenericArguments().Length - 1; + + for (var i = 0; i < fullResult.Length; ++i) + using (var ts = source.Take(i).AsTestingSequence()) + Assert.That(tuplewise(ts, resultSelector), Is.EqualTo(fullResult.Take(i - arity + 1))); + } + + private void TuplewiseNWideInt(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector) + { + const int rangeLen = 100; + var arity = resultSelector.GetType().GetGenericArguments().Length - 1; + + TuplewiseNWide( + tuplewise, + resultSelector, + Enumerable.Range(1, rangeLen), + Enumerable.Range(1, rangeLen - (arity - 1)).Select(x => x * arity + Enumerable.Range(1, arity - 1).Sum()).ToArray() + ); + } + + private void TuplewiseNWideString(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector) + { + const string alphabet = "abcdefghijklmnopqrstuvwxyz"; + var arity = resultSelector.GetType().GetGenericArguments().Length - 1; + + TuplewiseNWide( + tuplewise, + resultSelector, + alphabet, + Enumerable.Range(0, alphabet.Length - (arity - 1)).Select(i => alphabet.Skip(i).Take(arity)).ToArray() + ); + } + +<# const int max = 4; + const string alphabet = "abcdefghijklmnopqrstuvwxyz"; +#> + [Test] + public void TuplewiseIsLazy() + { +<# for (int i = 2; i <= max; ++i) { + var funcTypeArgs = string.Join(" ", Enumerable.Repeat("object,", i).Concat(Enumerable.Repeat(" ", max - i))); +#> + new BreakingSequence().Tuplewise(BreakingFunc.Of<<#= funcTypeArgs #> int>()); +<# } #> + } + + [Test] + public void TuplewiseIntegers() + { +<# for (int i = 2; i <= max; ++i) { + var funcTypeArgs = string.Join(" ", Enumerable.Repeat("int,", i).Concat(Enumerable.Repeat(" ", max - i))); + var functorArgs = string.Join(", ", Enumerable.Range(1, i).Select(j => alphabet.Substring(j - 1, 1))) + new string(' ', 3 * (max - i)); + var functorBody = string.Join(" + ", Enumerable.Range(1, i).Select(j => alphabet.Substring(j - 1, 1))) + new string(' ', 4 * (max - i)); +#> + TuplewiseNWideInt int>>((source, func) => MoreEnumerable.Tuplewise(source, func), (<#= functorArgs #>) => <#= functorBody #>); +<# } #> + } + + [Test] + public void TuplewiseStrings() + { +<# for (int i = 2; i <= max; ++i) { + var funcTypeArgs = string.Join(" ", Enumerable.Repeat("char,", i).Concat(Enumerable.Repeat(" ", max - i))); + var functorArgs = string.Join(", ", Enumerable.Range(1, i).Select(j => alphabet.Substring(j - 1, 1))) + new string(' ', 3 * (max - i)); +#> + TuplewiseNWideString string>>((source, func) => MoreEnumerable.Tuplewise(source, func), (<#= functorArgs #>) => string.Join(string.Empty, <#= functorArgs #>)); +<# } #> + } + } +} diff --git a/MoreLinq/Extensions.g.cs b/MoreLinq/Extensions.g.cs index 0b1211058..1d619b008 100644 --- a/MoreLinq/Extensions.g.cs +++ b/MoreLinq/Extensions.g.cs @@ -3893,13 +3893,12 @@ public static partial class PairwiseExtension /// only returned as the predecessor of the second element. /// /// The type of the elements of . - /// The type of the element of the returned sequence. + /// The type of the elements of the returned sequence. /// The source sequence. - /// A transform function to apply to - /// each pair of sequence. - /// - /// Returns the resulting sequence. - /// + /// A transform function to apply to each pair of . + /// Returns the resulting sequence. + /// is null + /// is null /// /// This operator uses deferred execution and streams its results. /// @@ -6670,6 +6669,73 @@ public static TResult TrySingle(this IEnumerable so } + /// Tuplewise extension. + + [GeneratedCode("MoreLinq.ExtensionsGenerator", "1.0.0.0")] + public static partial class TuplewiseExtension + { + /// + /// Returns a sequence resulting from applying a function to each + /// element in the source sequence and its + /// predecessor, with the exception of the first element which is + /// only returned as the predecessor of the second element. + /// + /// The type of the elements of . + /// The type of the elements of the returned sequence. + /// The source sequence. + /// A transform function to apply to each pair of . + /// Returns the resulting sequence. + /// is null + /// is null + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable Tuplewise(this IEnumerable source, Func resultSelector) + => MoreEnumerable.Tuplewise(source, resultSelector); + + /// + /// Returns a sequence resulting from applying a function to each + /// element in the source sequence and its + /// 2 predecessors, with the exception of the first and second elements which are + /// only returned as the predecessors of the third element. + /// + /// The type of the elements of . + /// The type of the elements of the returned sequence. + /// The source sequence. + /// A transform function to apply to each triplet of . + /// Returns the resulting sequence. + /// is null + /// is null + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable Tuplewise(this IEnumerable source, Func resultSelector) + => MoreEnumerable.Tuplewise(source, resultSelector); + + /// + /// Returns a sequence resulting from applying a function to each + /// element in the source sequence and its + /// 3 predecessors, with the exception of the first 3 elements which are + /// only returned as the predecessors of the 4th element. + /// + /// The type of the elements of . + /// The type of the elements of the returned sequence. + /// The source sequence. + /// A transform function to apply to each 4-tuple of . + /// Returns the resulting sequence. + /// is null + /// is null + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable Tuplewise(this IEnumerable source, Func resultSelector) + => MoreEnumerable.Tuplewise(source, resultSelector); + + } + /// Window extension. [GeneratedCode("MoreLinq.ExtensionsGenerator", "1.0.0.0")] diff --git a/MoreLinq/MoreLinq.csproj b/MoreLinq/MoreLinq.csproj index dbe55aa50..a09c60eab 100644 --- a/MoreLinq/MoreLinq.csproj +++ b/MoreLinq/MoreLinq.csproj @@ -102,6 +102,7 @@ - Transpose - TraverseBreadthFirst - TraverseDepthFirst + - Triplewise - TrySingle - Unfold - Window @@ -172,6 +173,10 @@ TextTemplatingFileGenerator ToDelimitedString.g.cs + + TextTemplatingFileGenerator + Tuplewise.g.cs + @@ -236,6 +241,11 @@ True ToDelimitedString.g.tt + + True + True + Tuplewise.g.tt + diff --git a/MoreLinq/Pairwise.cs b/MoreLinq/Pairwise.cs index 9e262e85d..a134bdd9b 100644 --- a/MoreLinq/Pairwise.cs +++ b/MoreLinq/Pairwise.cs @@ -29,13 +29,12 @@ static partial class MoreEnumerable /// only returned as the predecessor of the second element. /// /// The type of the elements of . - /// The type of the element of the returned sequence. + /// The type of the elements of the returned sequence. /// The source sequence. - /// A transform function to apply to - /// each pair of sequence. - /// - /// Returns the resulting sequence. - /// + /// A transform function to apply to each pair of . + /// Returns the resulting sequence. + /// is null + /// is null /// /// This operator uses deferred execution and streams its results. /// @@ -49,24 +48,6 @@ static partial class MoreEnumerable /// public static IEnumerable Pairwise(this IEnumerable source, Func resultSelector) - { - if (source == null) throw new ArgumentNullException(nameof(source)); - if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); - - return _(); IEnumerable _() - { - using var e = source.GetEnumerator(); - - if (!e.MoveNext()) - yield break; - - var previous = e.Current; - while (e.MoveNext()) - { - yield return resultSelector(previous, e.Current); - previous = e.Current; - } - } - } + => source.Tuplewise(resultSelector); } } diff --git a/MoreLinq/Tuplewise.g.cs b/MoreLinq/Tuplewise.g.cs new file mode 100644 index 000000000..38b23bff7 --- /dev/null +++ b/MoreLinq/Tuplewise.g.cs @@ -0,0 +1,152 @@ +#region License and Terms +// MoreLINQ - Extensions to LINQ to Objects +// Copyright (c) 2019 Phillip Palk. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +namespace MoreLinq +{ + using System; + using System.Collections.Generic; + + partial class MoreEnumerable + { + /// + /// Returns a sequence resulting from applying a function to each + /// element in the source sequence and its + /// predecessor, with the exception of the first element which is + /// only returned as the predecessor of the second element. + /// + /// The type of the elements of . + /// The type of the elements of the returned sequence. + /// The source sequence. + /// A transform function to apply to each pair of . + /// Returns the resulting sequence. + /// is null + /// is null + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable Tuplewise(this IEnumerable source, Func resultSelector) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + using var e = source.GetEnumerator(); + + if (!e.MoveNext()) + yield break; + var predecessor1 = e.Current; + + while (e.MoveNext()) + { + yield return resultSelector(predecessor1, e.Current); + (predecessor1) = (e.Current); + } + } + } + + /// + /// Returns a sequence resulting from applying a function to each + /// element in the source sequence and its + /// 2 predecessors, with the exception of the first and second elements which are + /// only returned as the predecessors of the third element. + /// + /// The type of the elements of . + /// The type of the elements of the returned sequence. + /// The source sequence. + /// A transform function to apply to each triplet of . + /// Returns the resulting sequence. + /// is null + /// is null + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable Tuplewise(this IEnumerable source, Func resultSelector) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + using var e = source.GetEnumerator(); + + if (!e.MoveNext()) + yield break; + var predecessor1 = e.Current; + + if (!e.MoveNext()) + yield break; + var predecessor2 = e.Current; + + while (e.MoveNext()) + { + yield return resultSelector(predecessor1, predecessor2, e.Current); + (predecessor1, predecessor2) = (predecessor2, e.Current); + } + } + } + + /// + /// Returns a sequence resulting from applying a function to each + /// element in the source sequence and its + /// 3 predecessors, with the exception of the first 3 elements which are + /// only returned as the predecessors of the 4th element. + /// + /// The type of the elements of . + /// The type of the elements of the returned sequence. + /// The source sequence. + /// A transform function to apply to each 4-tuple of . + /// Returns the resulting sequence. + /// is null + /// is null + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable Tuplewise(this IEnumerable source, Func resultSelector) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + using var e = source.GetEnumerator(); + + if (!e.MoveNext()) + yield break; + var predecessor1 = e.Current; + + if (!e.MoveNext()) + yield break; + var predecessor2 = e.Current; + + if (!e.MoveNext()) + yield break; + var predecessor3 = e.Current; + + while (e.MoveNext()) + { + yield return resultSelector(predecessor1, predecessor2, predecessor3, e.Current); + (predecessor1, predecessor2, predecessor3) = (predecessor2, predecessor3, e.Current); + } + } + } + + } +} diff --git a/MoreLinq/Tuplewise.g.tt b/MoreLinq/Tuplewise.g.tt new file mode 100644 index 000000000..721215978 --- /dev/null +++ b/MoreLinq/Tuplewise.g.tt @@ -0,0 +1,90 @@ +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ output extension=".cs" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Globalization" #> +<#@ import namespace="System.Linq" #> +#region License and Terms +// MoreLINQ - Extensions to LINQ to Objects +// Copyright (c) 2019 Phillip Palk. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +namespace MoreLinq +{ + using System; + using System.Collections.Generic; + + partial class MoreEnumerable + { +<# const int max = 4; + var overloads = + from i in Enumerable.Range(2, max - 1) + let istr = i.ToString(CultureInfo.InvariantCulture) + let im1str = (i - 1).ToString(CultureInfo.InvariantCulture) + select new + { + Ts = string.Join(", ", Enumerable.Repeat("TSource", i)), + Nth = i == 2 ? "second" : i == 3 ? "third" : istr + "th", + NTuple = i == 2 ? "pair" : i == 3 ? "triplet" : istr + "-tuple", + PIsAre = (i - 1) == 1 ? "is" : "are", + Predecessors = (i - 1) == 1 ? "predecessor" : "predecessors", + PPredecessors = (i - 1) == 1 ? "predecessor" : im1str + " predecessors", + PElements = (i - 1) == 1 ? "first element" : (i - 1) == 2 ? "first and second elements" : ("first " + im1str + " elements"), + PredecessorNames = Enumerable.Range(1, i - 1).Select(n => "predecessor" + n.ToString(CultureInfo.InvariantCulture)) + }; + + foreach (var e in overloads) { #> + /// + /// Returns a sequence resulting from applying a function to each + /// element in the source sequence and its + /// <#= e.PPredecessors #>, with the exception of the <#= e.PElements #> which <#= e.PIsAre #> + /// only returned as the <#= e.Predecessors #> of the <#= e.Nth #> element. + /// + /// The type of the elements of . + /// The type of the elements of the returned sequence. + /// The source sequence. + /// A transform function to apply to each <#= e.NTuple #> of . + /// Returns the resulting sequence. + /// is null + /// is null + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable Tuplewise(this IEnumerable source, Func<<#= e.Ts #>, TResult> resultSelector) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + using var e = source.GetEnumerator(); + +<# foreach (var predecessor in e.PredecessorNames) { #> + if (!e.MoveNext()) + yield break; + var <#= predecessor #> = e.Current; + +<# } #> + while (e.MoveNext()) + { + yield return resultSelector(<#= string.Join(", ", e.PredecessorNames.Concat(new[] { "e.Current" })) #>); + (<#= string.Join(", ", e.PredecessorNames) #>) = (<#= string.Join(", ", e.PredecessorNames.Skip(1).Concat(new[] { "e.Current" })) #>); + } + } + } + +<# } #> + } +} diff --git a/README.md b/README.md index 65340dc87..eea2012e9 100644 --- a/README.md +++ b/README.md @@ -682,6 +682,12 @@ that indicates the cardinality of the result sequence. This method has 2 overloads. +### Tuplewise + +Returns a sequence resulting from applying a function to each element in the +source sequence and its N-1 predecessors, with the exception of the first N-1 +elements which are only returned as the predecessors of the Nth element. + ### Unfold Returns a sequence generated by applying a state to the generator function, From 297e9129109ff754c7d9cbbd3b40a90047632684 Mon Sep 17 00:00:00 2001 From: Phillip Palk Date: Sat, 16 Nov 2019 06:45:42 +1000 Subject: [PATCH 2/4] Fixed mistake in .csproj description. --- MoreLinq/MoreLinq.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MoreLinq/MoreLinq.csproj b/MoreLinq/MoreLinq.csproj index a09c60eab..4deb1cd7f 100644 --- a/MoreLinq/MoreLinq.csproj +++ b/MoreLinq/MoreLinq.csproj @@ -102,8 +102,8 @@ - Transpose - TraverseBreadthFirst - TraverseDepthFirst - - Triplewise - TrySingle + - Tuplewise - Unfold - Window - WindowLeft From 8e683b66eaf764a84b9825da2e7d8379ddf36da4 Mon Sep 17 00:00:00 2001 From: Phillip Palk Date: Sat, 7 Dec 2019 09:53:05 +1000 Subject: [PATCH 3/4] Apply suggestions for code simplication from code review Co-Authored-By: Atif Aziz --- MoreLinq.Test/TuplewiseTest.g.tt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/MoreLinq.Test/TuplewiseTest.g.tt b/MoreLinq.Test/TuplewiseTest.g.tt index 8bf12b4bf..80d65c89c 100644 --- a/MoreLinq.Test/TuplewiseTest.g.tt +++ b/MoreLinq.Test/TuplewiseTest.g.tt @@ -29,7 +29,7 @@ namespace MoreLinq.Test [TestFixture] public class TuplewiseTest { - private void TuplewiseNWide(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector, IEnumerable source, params TResult[] fullResult) + void TuplewiseNWide(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector, IEnumerable source, params TResult[] fullResult) { var arity = resultSelector.GetType().GetGenericArguments().Length - 1; @@ -38,7 +38,7 @@ namespace MoreLinq.Test Assert.That(tuplewise(ts, resultSelector), Is.EqualTo(fullResult.Take(i - arity + 1))); } - private void TuplewiseNWideInt(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector) + void TuplewiseNWideInt(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector) { const int rangeLen = 100; var arity = resultSelector.GetType().GetGenericArguments().Length - 1; @@ -51,7 +51,7 @@ namespace MoreLinq.Test ); } - private void TuplewiseNWideString(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector) + void TuplewiseNWideString(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector) { const string alphabet = "abcdefghijklmnopqrstuvwxyz"; var arity = resultSelector.GetType().GetGenericArguments().Length - 1; @@ -70,7 +70,7 @@ namespace MoreLinq.Test [Test] public void TuplewiseIsLazy() { -<# for (int i = 2; i <= max; ++i) { +<# for (var i = 2; i <= max; ++i) { var funcTypeArgs = string.Join(" ", Enumerable.Repeat("object,", i).Concat(Enumerable.Repeat(" ", max - i))); #> new BreakingSequence().Tuplewise(BreakingFunc.Of<<#= funcTypeArgs #> int>()); @@ -80,23 +80,23 @@ namespace MoreLinq.Test [Test] public void TuplewiseIntegers() { -<# for (int i = 2; i <= max; ++i) { +<# for (var i = 2; i <= max; ++i) { var funcTypeArgs = string.Join(" ", Enumerable.Repeat("int,", i).Concat(Enumerable.Repeat(" ", max - i))); var functorArgs = string.Join(", ", Enumerable.Range(1, i).Select(j => alphabet.Substring(j - 1, 1))) + new string(' ', 3 * (max - i)); var functorBody = string.Join(" + ", Enumerable.Range(1, i).Select(j => alphabet.Substring(j - 1, 1))) + new string(' ', 4 * (max - i)); #> - TuplewiseNWideInt int>>((source, func) => MoreEnumerable.Tuplewise(source, func), (<#= functorArgs #>) => <#= functorBody #>); + TuplewiseNWideInt int>>(MoreEnumerable.Tuplewise, (<#= functorArgs #>) => <#= functorBody #>); <# } #> } [Test] public void TuplewiseStrings() { -<# for (int i = 2; i <= max; ++i) { +<# for (var i = 2; i <= max; ++i) { var funcTypeArgs = string.Join(" ", Enumerable.Repeat("char,", i).Concat(Enumerable.Repeat(" ", max - i))); var functorArgs = string.Join(", ", Enumerable.Range(1, i).Select(j => alphabet.Substring(j - 1, 1))) + new string(' ', 3 * (max - i)); #> - TuplewiseNWideString string>>((source, func) => MoreEnumerable.Tuplewise(source, func), (<#= functorArgs #>) => string.Join(string.Empty, <#= functorArgs #>)); + TuplewiseNWideString string>>(MoreEnumerable.Tuplewise, (<#= functorArgs #>) => string.Join(string.Empty, <#= functorArgs #>)); <# } #> } } From d6a99b3e3d66aa1dde61b52303f686733c62f8a9 Mon Sep 17 00:00:00 2001 From: Phillip Palk Date: Sat, 7 Dec 2019 09:48:20 +1000 Subject: [PATCH 4/4] Move methods that don't need to be templated out of the TuplewiseTest T4 template and into a separate partial class. --- MoreLinq.Test/TuplewiseTest.cs | 64 ++++++++++++++++++++++++++++++++ MoreLinq.Test/TuplewiseTest.g.cs | 50 ++++--------------------- MoreLinq.Test/TuplewiseTest.g.tt | 38 +------------------ 3 files changed, 72 insertions(+), 80 deletions(-) create mode 100644 MoreLinq.Test/TuplewiseTest.cs diff --git a/MoreLinq.Test/TuplewiseTest.cs b/MoreLinq.Test/TuplewiseTest.cs new file mode 100644 index 000000000..14b677eff --- /dev/null +++ b/MoreLinq.Test/TuplewiseTest.cs @@ -0,0 +1,64 @@ +#region License and Terms +// MoreLINQ - Extensions to LINQ to Objects +// Copyright (c) 2019 Phillip Palk. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +namespace MoreLinq.Test +{ + using System; + using System.Collections.Generic; + using NUnit.Framework; + + [TestFixture] + public partial class TuplewiseTest + { + // NOTE: See the T4 template TuplewiseTest.g.tt for the actual tests + + void TuplewiseNWide(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector, IEnumerable source, params TResult[] fullResult) + { + var arity = resultSelector.GetType().GetGenericArguments().Length - 1; + + for (var i = 0; i < fullResult.Length; ++i) + using (var ts = source.Take(i).AsTestingSequence()) + Assert.That(tuplewise(ts, resultSelector), Is.EqualTo(fullResult.Take(i - arity + 1))); + } + + void TuplewiseNWideInt(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector) + { + const int rangeLen = 100; + var arity = resultSelector.GetType().GetGenericArguments().Length - 1; + + TuplewiseNWide( + tuplewise, + resultSelector, + Enumerable.Range(1, rangeLen), + Enumerable.Range(1, rangeLen - (arity - 1)).Select(x => x * arity + Enumerable.Range(1, arity - 1).Sum()).ToArray() + ); + } + + void TuplewiseNWideString(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector) + { + const string alphabet = "abcdefghijklmnopqrstuvwxyz"; + var arity = resultSelector.GetType().GetGenericArguments().Length - 1; + + TuplewiseNWide( + tuplewise, + resultSelector, + alphabet, + Enumerable.Range(0, alphabet.Length - (arity - 1)).Select(i => alphabet.Skip(i).Take(arity)).ToArray() + ); + } + } +} diff --git a/MoreLinq.Test/TuplewiseTest.g.cs b/MoreLinq.Test/TuplewiseTest.g.cs index bdb84e273..15f52e618 100644 --- a/MoreLinq.Test/TuplewiseTest.g.cs +++ b/MoreLinq.Test/TuplewiseTest.g.cs @@ -21,44 +21,8 @@ namespace MoreLinq.Test using System.Collections.Generic; using NUnit.Framework; - [TestFixture] - public class TuplewiseTest + public partial class TuplewiseTest { - private void TuplewiseNWide(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector, IEnumerable source, params TResult[] fullResult) - { - var arity = resultSelector.GetType().GetGenericArguments().Length - 1; - - for (var i = 0; i < fullResult.Length; ++i) - using (var ts = source.Take(i).AsTestingSequence()) - Assert.That(tuplewise(ts, resultSelector), Is.EqualTo(fullResult.Take(i - arity + 1))); - } - - private void TuplewiseNWideInt(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector) - { - const int rangeLen = 100; - var arity = resultSelector.GetType().GetGenericArguments().Length - 1; - - TuplewiseNWide( - tuplewise, - resultSelector, - Enumerable.Range(1, rangeLen), - Enumerable.Range(1, rangeLen - (arity - 1)).Select(x => x * arity + Enumerable.Range(1, arity - 1).Sum()).ToArray() - ); - } - - private void TuplewiseNWideString(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector) - { - const string alphabet = "abcdefghijklmnopqrstuvwxyz"; - var arity = resultSelector.GetType().GetGenericArguments().Length - 1; - - TuplewiseNWide( - tuplewise, - resultSelector, - alphabet, - Enumerable.Range(0, alphabet.Length - (arity - 1)).Select(i => alphabet.Skip(i).Take(arity)).ToArray() - ); - } - [Test] public void TuplewiseIsLazy() { @@ -70,17 +34,17 @@ public void TuplewiseIsLazy() [Test] public void TuplewiseIntegers() { - TuplewiseNWideInt>((source, func) => MoreEnumerable.Tuplewise(source, func), (a, b ) => a + b ); - TuplewiseNWideInt>((source, func) => MoreEnumerable.Tuplewise(source, func), (a, b, c ) => a + b + c ); - TuplewiseNWideInt>((source, func) => MoreEnumerable.Tuplewise(source, func), (a, b, c, d) => a + b + c + d); + TuplewiseNWideInt>(MoreEnumerable.Tuplewise, (a, b ) => a + b ); + TuplewiseNWideInt>(MoreEnumerable.Tuplewise, (a, b, c ) => a + b + c ); + TuplewiseNWideInt>(MoreEnumerable.Tuplewise, (a, b, c, d) => a + b + c + d); } [Test] public void TuplewiseStrings() { - TuplewiseNWideString>((source, func) => MoreEnumerable.Tuplewise(source, func), (a, b ) => string.Join(string.Empty, a, b )); - TuplewiseNWideString>((source, func) => MoreEnumerable.Tuplewise(source, func), (a, b, c ) => string.Join(string.Empty, a, b, c )); - TuplewiseNWideString>((source, func) => MoreEnumerable.Tuplewise(source, func), (a, b, c, d) => string.Join(string.Empty, a, b, c, d)); + TuplewiseNWideString>(MoreEnumerable.Tuplewise, (a, b ) => string.Join(string.Empty, a, b )); + TuplewiseNWideString>(MoreEnumerable.Tuplewise, (a, b, c ) => string.Join(string.Empty, a, b, c )); + TuplewiseNWideString>(MoreEnumerable.Tuplewise, (a, b, c, d) => string.Join(string.Empty, a, b, c, d)); } } } diff --git a/MoreLinq.Test/TuplewiseTest.g.tt b/MoreLinq.Test/TuplewiseTest.g.tt index 80d65c89c..68b9370d8 100644 --- a/MoreLinq.Test/TuplewiseTest.g.tt +++ b/MoreLinq.Test/TuplewiseTest.g.tt @@ -26,44 +26,8 @@ namespace MoreLinq.Test using System.Collections.Generic; using NUnit.Framework; - [TestFixture] - public class TuplewiseTest + public partial class TuplewiseTest { - void TuplewiseNWide(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector, IEnumerable source, params TResult[] fullResult) - { - var arity = resultSelector.GetType().GetGenericArguments().Length - 1; - - for (var i = 0; i < fullResult.Length; ++i) - using (var ts = source.Take(i).AsTestingSequence()) - Assert.That(tuplewise(ts, resultSelector), Is.EqualTo(fullResult.Take(i - arity + 1))); - } - - void TuplewiseNWideInt(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector) - { - const int rangeLen = 100; - var arity = resultSelector.GetType().GetGenericArguments().Length - 1; - - TuplewiseNWide( - tuplewise, - resultSelector, - Enumerable.Range(1, rangeLen), - Enumerable.Range(1, rangeLen - (arity - 1)).Select(x => x * arity + Enumerable.Range(1, arity - 1).Sum()).ToArray() - ); - } - - void TuplewiseNWideString(Func, TFunc, IEnumerable> tuplewise, TFunc resultSelector) - { - const string alphabet = "abcdefghijklmnopqrstuvwxyz"; - var arity = resultSelector.GetType().GetGenericArguments().Length - 1; - - TuplewiseNWide( - tuplewise, - resultSelector, - alphabet, - Enumerable.Range(0, alphabet.Length - (arity - 1)).Select(i => alphabet.Skip(i).Take(arity)).ToArray() - ); - } - <# const int max = 4; const string alphabet = "abcdefghijklmnopqrstuvwxyz"; #>