-
-
Notifications
You must be signed in to change notification settings - Fork 12
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
Move range #584
base: master
Are you sure you want to change the base?
Move range #584
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider the following desire:
Enumerable.Range(1, 10)
.Select(x => x.ToString())
.Move(^5..^2, 10);
What would be the expected sequence? What is your code returning? Also consider what would happen if to
was changed to an Index
, such that it was .Move(^5..^2, ^0)
.
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #584 +/- ##
==========================================
- Coverage 93.30% 93.03% -0.27%
==========================================
Files 242 255 +13
Lines 7767 8141 +374
Branches 1596 1618 +22
==========================================
+ Hits 7247 7574 +327
- Misses 329 358 +29
- Partials 191 209 +18 ☔ View full report in Codecov by Sentry. |
Can deferred execution still be maintained if the 'from end' operator is used? I have tried to avoid it by checking each index: var length = 0;
if (range.Start.IsFromEnd || range.End.IsFromEnd || toIndex.IsFromEnd)
{
length = source.GetCollectionCount();
}
var fromIndex = range.Start.IsFromEnd ? length - range.Start.Value : range.Start.Value;
var count = (range.End.IsFromEnd ? length - range.End.Value : range.End.Value) - fromIndex;
var to = toIndex.IsFromEnd ? length - toIndex.Value : toIndex.Value;
return source.Move
(
fromIndex,
count,
to
); I think that it may mislead the user if they decide to go for the overload rather than the original. |
Take a look at the
NB: in some of these cases, there are corner cases to consider, such as if the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sorry, but I think you may still be missing the point about how ^
indexes are actually interpreted. Please review the TakeRangeFromEndIterator
method for the complexities involved here.
A simple call to the existing Move
method is only valid for the case where all three values are !.IsFromEnd
. A separate iterator method will be required to handle any other case.
Source/SuperLinq/Move.cs
Outdated
length = source.TryGetCollectionCount(); | ||
if (!length.HasValue) | ||
{ | ||
length = source.GetCollectionCount(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if TryGetCollectionCount()
fails to return a value, then GetCollectionCount()
will throw an exception. try calling Enumerable.Range(1, 10).Select(Identity).GetCollectionCount()
.
Source/SuperLinq/Move.cs
Outdated
length = source.GetCollectionCount(); | ||
} | ||
} | ||
var fromIndex = range.Start.IsFromEnd ? range.Start.GetOffset(length.Value) : range.Start.Value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review https://github.com/viceroypenguin/SuperLinq/blob/master/Source/SuperLinq/Take.cs#L87-L92 for why you cannot do this here.
Apologies for the silence, I'm struggling to find a use for a buffer. In the TakeFromEndIterator it makes sense since the length to take is known and the distance from the end is also known (0). For example, in the Move case:
We can infer the length of the buffer from the difference between the start and end range. The buffer can be added to when enumerating through, but since the number of elements is unknown, the values could be dropped from the buffer once it has reached capacity. If there is a different between start.IsFromEnd and end.IsFromEnd the length of the buffer cannot be inferred. |
This is correct. That's why a buffer must be used in at least some of these cases. If both are |
Why would moving an invalid range result in an empty sequence? Also, I believe that this scenario can also arise from differences in IsFromEnd in the range. I am having difficulty understanding how there could be an approach that would differ from the original implementation. Finding the number of elements seems to be required for all approaches that has parameters with Scenarios1.
Original method can be used without enumerating to find count. 2.
Cannot yield any elements until count is known. It is possible that elements could be moved to start of the IEnumerable. For example, Move(1, 3, ^5). If the number of elements is equal to 5. 3.
Cannot yield any elements until count is known. It's possible that the range's end occurs before the start. Yielding any value here would infringe on returning an empty sequence if end index < start index. 4.
Combination of 2 and 3. 5.
Same as 3. 6.
Same as 4. 7.
Cannot yield until count is known. Elements at start may be moved. 8.
Count must be known. Please let me know if I'm missing something, but my current understanding is that finding the count and relying on the existing |
Consider the following:
In this case, the entire sequence did not need to be buffered, only the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some legibility issues with this IMHO.
I've added an additional buffer for the case that the range has moved to a prior position in the enumerable. A more elegant solution is required, but there seems to be common themes between the two solved scenarios so far. |
Overload implementation and tests for and overload of
Move
that takes a range as a parameter. #27Overload just uses existing implementation of Move but takes range as parameter instead