Swift Error: 'Sequence' requires the types 'T' and 'ArraySlice T ' be equivalent
Your code compiles fine as Swift 3.1 (Xcode 8.3.3). The error
'Sequence' requires the types 'T' and 'ArraySlice<T>' be equivalent
occurs when compiling as Swift 4 (Xcode 9, currently beta), because then
the Sequence
protocol already defines the
associatedtype Element where Self.Element == Self.Iterator.Element
which conflicts with your definition. You can either choose a different
name for your type alias, or just remove it (and use T
instead):
public struct Matrix<T> where T: FloatingPoint, T: ExpressibleByFloatLiteral {
let rows: Int
let columns: Int
var grid: [T]
public init(rows: Int, columns: Int, repeatedValue: T) {
self.rows = rows
self.columns = columns
self.grid = [T](repeating: repeatedValue, count: rows * columns)
}
}
extension Matrix: Sequence {
public func makeIterator() -> AnyIterator<ArraySlice<T>> {
let endIndex = rows * columns
var nextRowStartIndex = 0
return AnyIterator {
if nextRowStartIndex == endIndex {
return nil
}
let currentRowStartIndex = nextRowStartIndex
nextRowStartIndex += self.columns
return self.grid[currentRowStartIndex..<nextRowStartIndex]
}
}
}
This compiles and runs with both Swift 3 and 4.
Collection' requires the types 'MyCollectionClass.Element' and 'Slice MyCollectionClass ' be equivalent
It's a completely useless error message (which I would encourage you to file a bug over) – the problem is twofold:
- You're confusing the compiler by interchangeably using
Int
andIndex
. - You're referring to
SubSequence
without actually having satisfied that associated type.
You can solve both of these by just defining type aliases in order to explicitly satisfy both the Index
and SubSequence
associated types:
public class MyCollectionClass<MyCollectionElement> {
var _values = [MyCollectionElement]()
}
extension MyCollectionClass: Collection {
public typealias Element = MyCollectionElement
public typealias Index = Int
// as ArraySlice is Array's SubSequence type.
public typealias SubSequence = ArraySlice<MyCollectionElement>
public var startIndex: Index {
return _values.startIndex
}
public var endIndex: Index {
return _values.endIndex
}
public func index(after: Index) -> Index {
return _values.index(after: after)
}
public subscript(position: Index) -> Element {
return _values[position]
}
public subscript(bounds: Range<Index>) -> SubSequence {
return _values[bounds]
}
}
Although note that you don't have to implement the subscript(bounds:)
requirement – Collection
offers a default implementation for that, which simply returns a Slice<Self>
.
Also, if possible, I would rename your (assumed) generic placeholder just to Element
, and have the compiler infer that the placeholder satisfies the Element
associated type from the subscript declaration:
public class MyCollectionClass<Element> {
var _values = [Element]()
}
extension MyCollectionClass: Collection {
public typealias Index = Int
public var startIndex: Index {
return _values.startIndex
}
public var endIndex: Index {
return _values.endIndex
}
public func index(after: Index) -> Index {
return _values.index(after: after)
}
public subscript(position: Index) -> Element {
return _values[position]
}
}
Why popFirst throws an error, but removeFirst works?
The error is improved in Swift 4.2:
error: ios.playground:4:25: error: '[T]' requires the types '[T]' and 'ArraySlice<T>' be equivalent to use 'popFirst'
return elements.popFirst() // ERROR!
^
You get the error because popFirst
is not defined for all Collection
s. It's only defined if the Collection
is its own SubSequence
type. Here's the implementation:
extension Collection where SubSequence == Self {
/// Removes and returns the first element of the collection.
///
/// - Returns: The first element of the collection if the collection is
/// not empty; otherwise, `nil`.
///
/// - Complexity: O(1)
@inlinable
public mutating func popFirst() -> Element? {
// TODO: swift-3-indexing-model - review the following
guard !isEmpty else { return nil }
let element = first!
self = self[index(after: startIndex)..<endIndex]
return element
}
}
The extension requires SubSequence == Self
. Self
(with a capital S) is the type of self
(with a lower-case s). It is the type on which you're calling popFirst
. In your code, Self
is Array<T>
, also spelled [T]
.
The constraint is necessary for this line of popFirst
to compile:
self = self[index(after: startIndex)..<endIndex]
^__^ ^_______________________________________^
| |
| This is a SubSequence.
|
This is a Self.
self[index(after: startIndex)..<endIndex]
is a SubSequence
.
Swift can only assign a SubSequence
to Self
if it knows that Self == SubSequence
.
Array
's SubSequence
type is ArraySlice
. Since ArraySlice
is not the same type as Array
, this extension doesn't apply to Array
.
Swift Error Cannot convert value of type '[String.Element]' (aka 'Array Character ') to expected argument type '[String]'
The problem is that Array(allWords[0])
produces [Character]
and not the [String]
that you need.
You can call map
on a String
(which is a collection of Character
s and use String.init
on each character to convert it to a String
). The result of the map
will be [String]
:
var arrayOfLetters = allWords[0].map(String.init)
Notes:
- When I tried this in a Playground, I was getting the mysterious message
Fatal error: Only BidirectionalCollections can be advanced by a negative amount
. This seems to be a Playground issue, because it works correctly in an app. - Just the word
"Leopards"
produces109,536
permutations.
Another Approach
Another approach to the problem is to realize that permute
doesn't have to work on [String]
. It could use [Character]
instead. Also, since you are always starting with a String
, why not pass that string to the outer permute
and let it create the [Character]
for you.
Finally, since it is logical to think that you might just want anagrams of the original word, make minStringLen
an optional with a value of nil
and just use word.count
if the value is not specified.
func permute(word: String, minStringLen: Int? = nil) -> Set<String> {
func permute(fromList: [Character], toList: [Character], minStringLen: Int, set: inout Set<String>) {
if toList.count >= minStringLen {
set.insert(String(toList))
}
if !fromList.isEmpty {
for (index, item) in fromList.enumerated() {
var newFrom = fromList
newFrom.remove(at: index)
permute(fromList: newFrom, toList: toList + [item], minStringLen: minStringLen, set: &set)
}
}
}
var set = Set<String>()
permute(fromList: Array(word), toList:[], minStringLen: minStringLen ?? word.count, set: &set)
return set
}
Examples:
print(permute(word: "foo", minStringLen: 1))
["of", "foo", "f", "fo", "o", "oof", "oo", "ofo"]
print(permute(word: "foo"))
["foo", "oof", "ofo"]
Swift Error: Cannot convert value of type 'ArraySlice' to expected argument type
You need to convert ArraySlice
to Array
using method Array(Slice<Type>)
if (self.points?.count >= 5) {
let lastFivePoints = Array(self.points![(self.points!.count-5)..<self.points!.count])
let angle = VectorCalculator.angleWithArrayOfPoints(lastFivePoints)
}
How can I perform an Array Slice in Swift?
The problem is that mentions[0...3]
returns an ArraySlice<String>
, not an Array<String>
. Therefore you could first use the Array(_:)
initialiser in order to convert the slice into an array:
let first3Elements : [String] // An Array of up to the first 3 elements.
if mentions.count >= 3 {
first3Elements = Array(mentions[0 ..< 3])
} else {
first3Elements = mentions
}
Or if you want to use an ArraySlice
(they are useful for intermediate computations, as they present a 'view' onto the original array, but are not designed for long term storage), you could subscript mentions
with the full range of indices in your else
:
let slice : ArraySlice<String> // An ArraySlice of up to the first 3 elements
if mentions.count >= 3 {
slice = mentions[0 ..< 3]
} else {
slice = mentions[mentions.indices] // in Swift 4: slice = mentions[...]
}
Although the simplest solution by far would be just to use the prefix(_:)
method, which will return an ArraySlice
of the first n elements, or a slice of the entire array if n exceeds the array count:
let slice = mentions.prefix(3) // ArraySlice of up to the first 3 elements
Referencing instance method 'stringify()' on 'Collection' requires the types 'Int' and 'Stringify' be equivalent
extension Collection where Iterator.Element == Stringify
has a “same type requirement” and defines an extension for collections whose elements are of the type Stringify
. But test
is an array of Int
, i.e. the elements conform to the Stringify
protocol. So what you want is
extension Collection where Iterator.Element : Stringify
or, equivalently,
extension Collection where Element : Stringify
The reason that
/// does work
[6,5,34].stringify()
compiles with your original definition is that the compiler infers the type of the array as [Stringify]
from the context.
let test: [Stringify] = [5,6,7]
test.stringify()
would compile as well.
Note that there is no need to cast self
in the extension method. You can simplify the implementation to
func stringify() -> [String] {
var strings = [String]()
for element in self {
strings.append(element.stringify())
}
return strings
}
or just
func stringify() -> [String] {
return self.map { $0.stringify() }
}
Swift closure: Cannot convert value of type '(_) - Bool' to expected argument type
Something flakey is happening with Swift's type inference. Give card
an explicit type and it will work.
return hand.filter({ (card: Card) -> Bool in return card.type == .Red })
You don't need the return type or the return:
return hand.filter({ (card: Card) in card.type == .Red })
Note: this works also:
return hand.filter({ ($0 as Card).type == .Red })
Fully specifying the .Red
enum value resolves the issue as well:
return hand.filter({ $0.type == Card.CardType.Red })
It was mentioned in the comments that if you move the definition of Card
into the same file as the filter, that it works. In fact, if you split the definition of the CardType
enum out from Card
and just move CardType
into the file with the filter, it works.
Implement `Array` & `ArraySlice` extension with a protocol instead
In order to call indices.groupSplitIndices()
you need the constraintIndices == CountableRange<Index>
on the collection extension,
and that requires Index
to be Strideable
:
extension RandomAccessCollection where Index: Strideable, Indices == CountableRange<Index> {
typealias EqualTest = (Iterator.Element, Iterator.Element) -> Bool
func groupSplitIndices(withEqualTest equal: EqualTest) -> [Index] {
return indices.groupSplitIndices(withEqualTest: {
equal(self[$0], self[$1])
})
}
}
extension CountableRange {
typealias EqualTest = (Element, Element) -> Bool
func groupSplitIndices(withEqualTest equal: EqualTest) -> [Element] {
// Dummy implementation:
return []
}
}
and this actually compiles with Swift 4 (Xcode 9 beta or Xcode 8.3.3 with the Swift 4 toolchain).
There is one problem though: The Swift 3 compiler in Xcode 8.3.3 crashes when compiling the
above code with the "Debug" configuration. That seems to be a compiler
bug, because it compiles without problem in the "Release" configuration,
and also with Xcode 9 or with Xcode 8.3.2 and the Swift 4 toolchain.
Here is a rough description how I figured out the above solution.
Let's start with your "Attempt 3":
extension RandomAccessCollection where Indices: CountableRange<Int>
// error: type 'Indices' constrained to non-protocol type 'CountableRange<Int>
Indices
can not be a subclass of or a type adopting CountableRange<Int>
, which means that we need a same-typre requirement:
extension RandomAccessCollection where Indices == CountableRange<Int>
This results in
// error: cannot subscript a value of type 'Self' with an index of type 'Int'
at self[$0]
and self[$1]
. The subscript
method of Collection
takes a Self.Index
parameter, so we change it to
extension RandomAccessCollection where Indices == CountableRange<Index>
// error: type 'Self.Index' does not conform to protocol '_Strideable'
So Index
must be Strideable
:
extension RandomAccessCollection where Index: Strideable, Indices == CountableRange<Index>
and that's it!
Related Topics
Apple Push Notifications Without Developer Account
Swiftui Nested Foreach Causes Unexpected Ordering
Round Currency Closest to Five
Swift Radio Streaming Avplayer
Enum Not Working in Custom Initializer
How to Scale/Position Nodes Swift Spritekit? Custom View
Uiimagepickercontroller Navigation Bar Tint Color Not Working with iOS 13
Codable/Decodable Should Decode Array with Strings
Swiftui List View Not Updating After Core Data Entity Updated in Another View
Charts Not Plotting in Tableviewcell
Comparing Two Enum Variables Regardless of Their Associated Values
Using "Codable" to Set Property Values Doesn't Work Through Inheritance
How to Find the Time Interval Remaining from Nstimer
Moving Skspritenode to Location of the Touch