-
Notifications
You must be signed in to change notification settings - Fork 419
Open
Description
This is a proposal to unify lookalike methods.
An example of use with Zip
is :
source1.Zip(source2) // ValueType creation overload
.PadSource1With(foo) // zip parametrisation
.PadSource2With(bar) // zip parametrisation
.Where((a,b) => ...) // zip consumption
. ...
Here are the methods signatures:
ZipEnumerable<T1, T2, TResult> Zip(this IEnumerable<T1> source1, IEnumerable<T2> source2, Func<T1, T2, TResult> func) => new ZipEnumerable(source1, source2, func);
ZipEnumerable<T1, T2, (T1, T2)> Zip(this IEnumerable<T1> source1, IEnumerable<T2> source2); // ValueType creation overload
// ZipEnumerable is a valid and honest IEnumerable
class ZipEnumerable<T1, T2, TResult> : IEnumerable<TResult>
{
// immutable configuration
readonly ZipConfiguration _configuration;
ZipEnumerable(IEnumerable<T1> source1, IEnumerable<T2> source2, Func<T1, T2, TResult> func)
{
}
// Return a enumerator that behaves according to the configuration
public IEnumerator<TResult> GetEnumerator()
{
...
}
// Configuration is fluent so updating it create an updated configuration and a new ZipEnumerable
ZipEnumerable<T1, T2, TResult> PadSource1With(T1 padValue) => new ZipEnumerable<T1, T2, TResult>(_source1, _source2, _func, _configuration.WithPadSource1Value(padValue));
... // more configuration methods
}
The fluent parametrisation pattern have some rules:
- configuration are immutable (for modification, create a new modified copy)
- any configuration is attainable from any other configuration (any set can eventually be unset)
- ?
Finally I expose the possibilities for Zip here as an example:
We have much more flexibility, for each source we can use one of those behavior :
- End the result sequence on source sequence end. (It's the default behavior and, when used for all sources, it's equivalent to ZipShortest)
- throw if the source is too short
- perform padding with a static value
- perform padding with the last value (we take care of empty source)
- ...
source1.Zip(source2)
.ThrowOnSource1Short(); // Throw only if source1 is too short
// stop if source2 too short (default behavior)
source1.Zip(source2)
.ThrowOnSource1Short() // Throw only if source1 is too short
.PadSource2WithLastOr(default); // Pad source2 with its last value (or the default value if it's empty)
source1.Zip(source2, source3, source4)
.ThrowOnShort() // ask for equi zip
.PadSource3With(foo); // This override the previous call and if source3 is too short it will be padded.
var zip1 = source1.Zip(source2); // zip1 is ZipShortest
var zip2 = zip1.PadSource1With(bar); // does not modify zip1
source1.Zip(source2); //ZipShortest (_do not do padding rule_)
source1.Zip(source2).ThrowOnShort(); // EquiZip
source1.Zip(source2).PadWithDefault(); // ZipLongest
Metadata
Metadata
Assignees
Labels
No labels