In Swift, I am trying to define a transpose operation for a Matrix
class which has a row view and a column view. The approach I am trying to take returns a new instances of Matrix
with the opposite typed view. A much simplified (though, still long) version of the code:
public protocol Storage {
typealias ElementType
init(size: Int)
}
public class NativeStorage<E>: Storage {
public typealias ElementType = E
public required init(size:Int) {}
}
public protocol StorageView {
typealias StorageType:Storage
typealias TransposeType
var storage:StorageType { get }
var window:[Range<Int>] { get }
init(storage:StorageType, window:[Range<Int>])
func transpose() -> TransposeType
}
A quick note here, ideally I would like to define TransposeType
as TransposeType:StorageView
. However, this cyclic reference is not allowed in Swift.
public class StorageRowView<S:Storage>: StorageView {
public typealias StorageType = S
public typealias TransposeType = StorageColumnView<S>
public var storage:StorageType
public var window:[Range<Int>]
public required init(storage:StorageType, window:[Range<Int>]) {
self.storage = storage
self.window = window
}
public func transpose() -> TransposeType {
return TransposeType(storage: storage, window: [window[1], window[0]])
}
}
public class StorageColumnView<S:Storage>: StorageView {
public typealias StorageType = S
public typealias TransposeType = StorageColumnView<S>
public var storage:StorageType
public var window:[Range<Int>]
public required init(storage:StorageType, window:[Range<Int>]) {
self.storage = storage
self.window = window
}
public func transpose() -> TransposeType {
return TransposeType(storage: storage, window: [window[1], window[0]])
}
}
class Matrix<ViewType:StorageView> {
typealias StorageType = ViewType.StorageType
typealias TransposeType = ViewType.TransposeType
var view:ViewType
init(rows: Int, cols: Int) {
let storage = StorageType(size: rows*cols)
view = ViewType(storage: storage, window: [0..<rows, 0..<cols])
}
init(view:ViewType) {
self.view = view
}
// this is an error because TransposeType is not defined
// as being of type StorageView
public func transpose() -> Matrix<TransposeType> {
return Matrix<TransposeType>(view: view.transpose())
}
}
The issue is that I can't write Matrix<TransposeType>
because the Swift compiler doesn't know that TransposeType
is actually of type StorageView
. I've been trying to figure out if there was a way to tell the compiler later on that TransposeType
is actually a StorageView
, but without any luck. Any ideas on how to get around this problem while keeping the general structure (specifically, having separate views, storage, and matrices is important)?
Also, it's a valid point to ask why Matrix
's type should be dependent on a view in the first place. That is related to a separate question I have (Design pattern for Swift using a protocol as a delegate).
Aucun commentaire:
Enregistrer un commentaire