This is quite confusing, but from what I can tell seems to be by design.
By inspecting each filtered collection's
indices property, we get a hint at what the issue is:
let filteredIndices = Array(filteredArray.indices) // [0, 1, 2, 3] let lazyFilteredIndices = Array(lazyFilteredArray.indices) // [1, 2, 3, 4]
This shows that the way the lazy filter works is by filtering out each index that doesn't match. So
lazyFilteredArray is actually the third element in the original array, not the third element in the new array.
Makes sense, since
lazyArrayElement isn't an
Array but a derived sequence it retains the original indices of the elements it points to (much like
ArraySlice). Though then the confusing part is to be able to access its elements with an
Int index: it's very much like the
String issue with subscripts, maybe minus performance details
I agree with Adam and Davide; this behavior is consistent with the collection model, although it is somewhat surprising in this particular example.
LazyFilterCollection reuses the index type (as well as some individual index values) of its base collection for convenience -- this enables the direct use of filtered indices in the original collection.
LazyFilterCollection<Array<T>> happens to have integer indices, it still requires explicit use of
Collection APIs like
index(_:, offsetBy:) to generate/manipulate indices -- integer operations won't do.
LazyFilterCollection was designed from scratch today, an argument could be made for it to define a custom index type. However, changing the index would be an extremely difficult proposition at this point, and since the current behavior is not incorrect, I think we should keep it.
One way to help reduce confusion is to simplify offset-based access to collection elements. We've talked about adding a generic offset-based subscript to
Collection; if we had that,
lazyFilteredArray[offset: 2] could be trusted to always return the third element in the filtered collection, not the original array.
This might help.
I understand now thanks to your explanation. Thank you.
I think it would be nice to have an offset-based subscript. I'll write it as an extension once. Thanks for the idea. lol.