Reputation: 1929
I have a problem with compiling tests cases in Swift. It looks like the compiler is loosing information about template type but other generic methods are working fine. What am I missing?
public class MatchNorm {
public static func resolve1<T:SequenceType where T.Generator.Element:MatchNormElement>(list: T, lti: LinearTransformation, accuracy: Double) -> LinearTransformation {
// no problem
return MatchNorm.resolve1(list, lti: lti, accuracy: accuracy)
}
public static func resolve2<T:SequenceType where T.Generator.Element:MatchNormElement>(list: T, lti: LinearTransformation, accuracy: Double) -> LinearTransformation {
for elem in list {
print(elem.x)
}
return lti
}
}
public class MatchNormTest: XCTestCase {
func testMatchNorm1() {
var list = [MatchNormElement]()
// compilation error here!
let ll = MatchNorm.resolve1(list, lti: LinearTransformation(1), accuracy: 0.001)
// MatchNormTest.swift:70:29: Cannot invoke 'resolve1' with an argument list of type '([MatchNormElement], lti: LinearTransformation, accuracy: Double)'
// MatchNormTest.swift:70:29: Expected an argument list of type '(T, lti: LinearTransformation, accuracy: Double)'
}
}
Update
MatchNormElement is a protocol, so I changed it to concrete type. Now it works.
func testMatchNorm1() {
var list = [Measurment]()
// works fine
let ll = MatchNorm.resolve1(list, lti: LinearTransformation(1), accuracy: 0.001)
}
Upvotes: 0
Views: 191
Reputation: 1585
This is reasonable for the compiler. Swift allows type conversion for a Concrete type to a Protocol based variable assignment.
However, Swift doesnot allow converting a set of Concrete Types to a set/array of Protocol by converting each. This is reasonable because of the following reasons:
Let suppose we have this constructs in place:
protocol IntType {}
extension Int: IntType{}
Now lets do the obvious thing:
let item = 12
let item2:IntType = item
Then the one that will look obvious to the eye: This wont compile for good reason.
let a = [1,2,3]
let b: [IntType] = a
Lets inspect the size of each Type before moving ahead:
sizeofValue(item) //8
sizeofValue(item2) //40
An array is a contagious memory of 8 bytes. So is Array a contagious memory of 40 bytes.
When we did this:
let b: [IntType] = a
We essentially tell the compiler to convert 8 bytes of array into 40 bytes of array and store it. Now as the array is contagious it has to destruct or reshuffle which is expensive task to do so. This hinders the performance and obviously you lose the type safety.
The compiler could this this transformation but Swift team decided for good reason that the user need to be explicit if they want this type transformation for 2 reasons: Performance and Type Safety.
Upvotes: 1