In Swift, how do you define an array of generics with type conforming Equatable?
Example:
struct File<T: Equatable> {
public var lines: [T]
private var lineCursor = 0
public var currentLine: T {
get { return lines[lineCursor] }
set { lineCursor = lines.index(where: { $0 == newValue }) ?? 0 }
}
}
struct Folder {
public var files: [File]? // compile time error
}
→ Reference to generic type 'File' requires arguments in <…>
…so far I tried:
[File<Any>]
→ Type 'Any' does not conform to protocol 'Equatable'
[File<Any: Equatable>]
→ Consecutive declarations on a line must be separated by ';'
[File<Any, Equatable>]
→ Generic type 'File' specialized with too many type parameters (got 2, but expected 1)
[File<Any & Equatable>]
→ Using 'Equatable' as a concrete type conforming to protocol 'Equatable' is not supported
[File<(Any: Equatable)>]
→ Cannot create a single-element tuple with an element label
[File<(Any, Equatable)>]
→ Type '(Any, Equatable)' does not conform to protocol 'Equatable'`
[File<(Any & Equatable)>]
→ Using 'Equatable' as a concrete type conforming to protocol 'Equatable' is not supported
[File<[Any: Equatable]>]
→ 'File' requires that 'Equatable' conform to 'Equatable'
[File<[Any, Equatable]>]
→ Consecutive declarations on a line must be separated by ';'
[File<[Any & Equatable]>]
→ 'File' requires that 'Equatable' conform to 'Equatable'
What is the correct syntax?
[EDIT] simplified the example
[EDIT] updated example:
class File<T: Equatable> {
var lines = [T]()
var lineCursor: Int = 0
var currentLine: T {
get { return lines[lineCursor] }
set { lineCursor = lines.index(where: { $0 == newValue }) ?? 0 }
}
var visible = true
}
class Folder {
var files = [File]() // Generic parameter 'Type' could not be inferred; I want this to be a mixed array
func currentLinesFromVisibleFiles() -> String {
return files.filter({ $0.visible }).map({ String(describing: $0.currentLine) }).joined(separator: "/")
}
}
var stringFile = File<String>()
stringFile.lines = ["strong", "string", "a", "b", "c"]
stringFile.currentLine = "string"
stringFile.visible = true
var intFile = File<Int>()
intFile.lines = [6, 12, 0, 489]
intFile.currentLine = 489
intFile.visible = true
var doubleFile = File<Double>()
doubleFile.lines = [92.12, 4.9753, 1.6]
doubleFile.currentLine = 92.12
doubleFile.visible = false
var boolFile = File<Bool>()
boolFile.lines = [true, false]
boolFile.currentLine = true
boolFile.visible = true
var folder = Folder()
folder.files = [stringFile, intFile, doubleFile, boolFile]
let output = folder.currentLinesFromVisibleFiles() // I want: "string/489/true"
Data
andFile
class?String
?Int
? That's what you need to use, notAny
. – rmaddyData
type? I don't really see a point in defining a type with a single instance property with a non-restricted generic type. Why don't you simply usepublic var lines: [Type]
in yourFile
type? Moreover, copying existing built-in type names is a bad idea as it will most probably lead to confusion for the readers of your code. – Dávid PásztorFloat
andBool
and also any future custom types that are Equatable. – Rudy PhillippsFile
orData
you need to do so with a specific (and Equatable) type.Any
isn'tEquatable
. – rmaddyType
? – Rudy Phillipps