young
(rtSwift)
1
?
I guess the second expresión implicitly call the suitable Array.init() to create a new array.
Why the first expression doesn’t do the implicit conversion but the second one does.
What’s the different in these two cases to have two different treatment ?
Ben_Cohen
(Ben Cohen)
2
Not quite. This isn't a question of implicit conversion, but of overloading at different points in the Collection hierarchy, along with the (sometime surprising) impact of Swift's overload resolution.
Sequence has the a method Sequence.reversed() -> [Element] which returns an Array. This is the only thing you can really do with something you can't iterate backwards – you have to slurp up all the elements into a buffer, then reverse it.
BidirectionalCollection can do better. It can return a lazy wrapper, because you can wrap a BiDi collection and then serve up its elements in reverse order.
If you just write let reversed = arrrayOfInt.reversed() it'll call the most specific method, so reversed will be a ReversedCollection<[Int]>.
But if you force the return value to [Int], the solver will discard that possibility, and it falls back to a less favored option that does work, which is the version on Sequence that returns an [Int].
So there is no conversion happening here – just a different method than maybe was expected being called.
5 Likes
young
(rtSwift)
3

Why with this:
var aaa = [1, 2, 3, 4, 5, 6, 7].reversed() // don’t force it to [Int]
let xxx = aaa.popLast() // compile error here
I get error:
Referencing instance method 'popLast()' on 'BidirectionalCollection' requires the types 'ReversedCollection<[Int]>' and 'ReversedCollection<[Int]>.SubSequence' (aka 'Slice<ReversedCollection<Array>>') be equivalent
How can I overcome this without forcing it to be a [Int], incurring copying? How can I operate on ReversedCollection<[Int]>?
Ben_Cohen
(Ben Cohen)
4
Create a subsequence of the reversed collection:
let reversed = [1, 2, 3, 4, 5, 6, 7].reversed()
var slice = reversed[...]
let element = slice.popLast()
Subsequences can have their last element popped easily because it's just a question of reducing the bounds of the slice, not actually mutating the underlying base collection.
3 Likes
Ben_Cohen
(Ben Cohen)
5
(the rather enigmatic error message is telling you that you can't pop the end off an arbitrary collection, but you can pop the end of a collection who's subsequence is Self)
1 Like
I've become used to this workaround, from running into this problem frequently enough, but I still wish it wasn't necessary. It does feel very hacky to do things like [...] when you don't explicitly care about the types involved, you just want something to work, like popLast.
I don't have any specific ideas for how to improve that, though. 