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

ScanBy: Update docs #882

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 22 additions & 20 deletions MoreLinq.Test/ScanByTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
// limitations under the License.
#endregion

#nullable enable

namespace MoreLinq.Test
{
using System;
Expand Down Expand Up @@ -48,10 +50,10 @@ public void ScanBy()
};

var result =
source.ScanBy(
item => item.First(),
key => (Element: default(string), Key: key, State: key - 1),
(state, key, item) => (item, char.ToUpperInvariant(key), state.State + 1));
source.ScanBy(
item => item.First(),
key => (Element: string.Empty, Key: key, State: key - 1),
atifaziz marked this conversation as resolved.
Show resolved Hide resolved
(state, key, item) => (item, char.ToUpperInvariant(key), state.State + 1));

result.AssertSequenceEqual(
KeyValuePair.Create('a', ("ana", 'A', 97)),
Expand Down Expand Up @@ -103,31 +105,31 @@ public void ScanByWithSomeNullKeys()
var result = source.ScanBy(c => c, _ => -1, (i, _, _) => i + 1);

result.AssertSequenceEqual(
KeyValuePair.Create("foo" , 0),
KeyValuePair.Create((string)null, 0),
KeyValuePair.Create("bar" , 0),
KeyValuePair.Create("baz" , 0),
KeyValuePair.Create((string)null, 1),
KeyValuePair.Create((string)null, 2),
KeyValuePair.Create("baz" , 1),
KeyValuePair.Create("bar" , 1),
KeyValuePair.Create((string)null, 3),
KeyValuePair.Create("foo" , 1));
KeyValuePair.Create<string?, int>("foo", 0),
Copy link
Contributor Author

@viceroypenguin viceroypenguin Nov 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type explicit to improve nullability behavior since KeyValuePair.Create() enforces a nullability value without target-typing to the sequence nullability type.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could go with typing just the one needed:

            result.AssertSequenceEqual(
                KeyValuePair.Create((string?)"foo", 0),
                KeyValuePair.Create((string?)null , 0),
                KeyValuePair.Create((string?)"bar", 0),
                KeyValuePair.Create((string?)"baz", 0),
                KeyValuePair.Create((string?)null , 1),
                KeyValuePair.Create((string?)null , 2),
                KeyValuePair.Create((string?)"baz", 1),
                KeyValuePair.Create((string?)"bar", 1),
                KeyValuePair.Create((string?)null , 3),
                KeyValuePair.Create((string?)"foo", 1));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered that, but I honestly like the other one better. Generally, to me, an explicit type cast like this feels like I may have done something wrong to need the cast, whereas target-typing using the explicit type of .Create() feels more natural. Just my opinion though.

KeyValuePair.Create<string?, int>(null , 0),
KeyValuePair.Create<string?, int>("bar", 0),
KeyValuePair.Create<string?, int>("baz", 0),
KeyValuePair.Create<string?, int>(null , 1),
KeyValuePair.Create<string?, int>(null , 2),
KeyValuePair.Create<string?, int>("baz", 1),
KeyValuePair.Create<string?, int>("bar", 1),
KeyValuePair.Create<string?, int>(null , 3),
KeyValuePair.Create<string?, int>("foo", 1));
}

[Test]
public void ScanByWithNullSeed()
{
var nil = (object)null;
var nil = (object?)null;
var source = new[] { "foo", null, "bar", null, "baz" };
var result = source.ScanBy(c => c, _ => nil, (_, _, _) => nil);

result.AssertSequenceEqual(
KeyValuePair.Create("foo" , nil),
KeyValuePair.Create((string)null, nil),
KeyValuePair.Create("bar" , nil),
KeyValuePair.Create((string)null, nil),
KeyValuePair.Create("baz" , nil));
KeyValuePair.Create<string?, object?>("foo", nil),
viceroypenguin marked this conversation as resolved.
Show resolved Hide resolved
KeyValuePair.Create<string?, object?>(null , nil),
KeyValuePair.Create<string?, object?>("bar", nil),
KeyValuePair.Create<string?, object?>(null , nil),
KeyValuePair.Create<string?, object?>("baz", nil));
}

[Test]
Expand Down
28 changes: 20 additions & 8 deletions MoreLinq/Extensions.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4920,20 +4920,26 @@ public static partial class ScanByExtension
/// Applies an accumulator function over sequence element keys,
/// returning the keys along with intermediate accumulator states.
/// </summary>
/// <typeparam name="TSource">Type of the elements of the source sequence.</typeparam>
/// <typeparam name="TSource">Type of the elements of the source
/// sequence.</typeparam>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <typeparam name="TState">Type of the state.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="keySelector">
/// A function that returns the key given an element.</param>
/// <param name="seedSelector">
/// A function to determine the initial value for the accumulator that is
/// invoked once per key encountered.</param>
/// A function to determine the initial value for the accumulator that
/// is invoked once per key encountered.</param>
/// <param name="accumulator">
/// An accumulator function invoked for each element.</param>
/// <returns>
/// A sequence of keys paired with intermediate accumulator states.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="source"/>, <paramref name="keySelector"/>, <paramref
/// name="seedSelector"/>, or <paramref name="accumulator"/> is <see
/// langword="null"/>.
/// </exception>

public static IEnumerable<KeyValuePair<TKey, TState>> ScanBy<TSource, TKey, TState>(
this IEnumerable<TSource> source,
Expand All @@ -4947,23 +4953,29 @@ public static IEnumerable<KeyValuePair<TKey, TState>> ScanBy<TSource, TKey, TSta
/// returning the keys along with intermediate accumulator states. An
/// additional parameter specifies the comparer to use to compare keys.
/// </summary>
/// <typeparam name="TSource">Type of the elements of the source sequence.</typeparam>
/// <typeparam name="TSource">Type of the elements of the source
/// sequence.</typeparam>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <typeparam name="TState">Type of the state.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="keySelector">
/// A function that returns the key given an element.</param>
/// <param name="seedSelector">
/// A function to determine the initial value for the accumulator that is
/// invoked once per key encountered.</param>
/// A function to determine the initial value for the accumulator that
/// is invoked once per key encountered.</param>
/// <param name="accumulator">
/// An accumulator function invoked for each element.</param>
/// <param name="comparer">The equality comparer to use to determine
/// whether or not keys are equal. If <c>null</c>, the default equality
/// comparer for <typeparamref name="TSource"/> is used.</param>
/// whether or not keys are equal. If <see langword="null"/>, <see
/// cref="EqualityComparer{T}.Default"/> is used.</param>
/// <returns>
/// A sequence of keys paired with intermediate accumulator states.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="source"/>, <paramref name="keySelector"/>, <paramref
/// name="seedSelector"/>, or <paramref name="accumulator"/> is <see
/// langword="null"/>.
/// </exception>

public static IEnumerable<KeyValuePair<TKey, TState>> ScanBy<TSource, TKey, TState>(
this IEnumerable<TSource> source,
Expand Down
30 changes: 21 additions & 9 deletions MoreLinq/ScanBy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,52 +26,64 @@ static partial class MoreEnumerable
/// Applies an accumulator function over sequence element keys,
/// returning the keys along with intermediate accumulator states.
/// </summary>
/// <typeparam name="TSource">Type of the elements of the source sequence.</typeparam>
/// <typeparam name="TSource">Type of the elements of the source
/// sequence.</typeparam>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <typeparam name="TState">Type of the state.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="keySelector">
/// A function that returns the key given an element.</param>
/// <param name="seedSelector">
/// A function to determine the initial value for the accumulator that is
/// invoked once per key encountered.</param>
/// A function to determine the initial value for the accumulator that
/// is invoked once per key encountered.</param>
/// <param name="accumulator">
/// An accumulator function invoked for each element.</param>
/// <returns>
/// A sequence of keys paired with intermediate accumulator states.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="source"/>, <paramref name="keySelector"/>, <paramref
/// name="seedSelector"/>, or <paramref name="accumulator"/> is <see
/// langword="null"/>.
/// </exception>

viceroypenguin marked this conversation as resolved.
Show resolved Hide resolved
public static IEnumerable<KeyValuePair<TKey, TState>> ScanBy<TSource, TKey, TState>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TKey, TState> seedSelector,
Func<TState, TKey, TSource, TState> accumulator)
{
return source.ScanBy(keySelector, seedSelector, accumulator, null);
return source.ScanBy(keySelector, seedSelector, accumulator, comparer: null);
viceroypenguin marked this conversation as resolved.
Show resolved Hide resolved
}

/// <summary>
/// Applies an accumulator function over sequence element keys,
/// returning the keys along with intermediate accumulator states. An
/// additional parameter specifies the comparer to use to compare keys.
/// </summary>
/// <typeparam name="TSource">Type of the elements of the source sequence.</typeparam>
/// <typeparam name="TSource">Type of the elements of the source
/// sequence.</typeparam>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <typeparam name="TState">Type of the state.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="keySelector">
/// A function that returns the key given an element.</param>
/// <param name="seedSelector">
/// A function to determine the initial value for the accumulator that is
/// invoked once per key encountered.</param>
/// A function to determine the initial value for the accumulator that
/// is invoked once per key encountered.</param>
/// <param name="accumulator">
/// An accumulator function invoked for each element.</param>
/// <param name="comparer">The equality comparer to use to determine
/// whether or not keys are equal. If <c>null</c>, the default equality
/// comparer for <typeparamref name="TSource"/> is used.</param>
/// whether or not keys are equal. If <see langword="null"/>, <see
/// cref="EqualityComparer{T}.Default"/> is used.</param>
/// <returns>
/// A sequence of keys paired with intermediate accumulator states.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="source"/>, <paramref name="keySelector"/>, <paramref
/// name="seedSelector"/>, or <paramref name="accumulator"/> is <see
/// langword="null"/>.
/// </exception>

public static IEnumerable<KeyValuePair<TKey, TState>> ScanBy<TSource, TKey, TState>(
this IEnumerable<TSource> source,
Expand Down