Generics 原始类型(Int、Float、Double)的泛型会创建奇怪的错误消息
这里有人能看一下代码,告诉我有什么问题吗?我基本上尝试构建两个通用函数,它们在某些原始类型上运行,如Generics 原始类型(Int、Float、Double)的泛型会创建奇怪的错误消息,generics,swift,Generics,Swift,这里有人能看一下代码,告诉我有什么问题吗?我基本上尝试构建两个通用函数,它们在某些原始类型上运行,如Int、Float、Double等 不幸的是,我不能让它正常工作。这是起作用的代码(部分): 它返回30的正确结果。好的,到目前为止还不错。当我试图传递一个Ints数组时,事情变得很奇怪: extension Int : SummableMultipliable {} var intVec : [Int] = [1,2,3,4] vec_dot(intVec, intVec) 砰!在以下位
Int
、Float
、Double
等
不幸的是,我不能让它正常工作。这是起作用的代码(部分):
它返回30的正确结果。好的,到目前为止还不错。当我试图传递一个Int
s数组时,事情变得很奇怪:
extension Int : SummableMultipliable {}
var intVec : [Int] = [1,2,3,4]
vec_dot(intVec, intVec)
砰!在以下位置引发异常:
let x = (a[1] * b[1]) as Double
*thread#1:tid=0x139dd0,0x00000001018527ad libswiftCore.dylib`swift\u dynamicCast+1229,queue='com.apple.main thread',stop reason=EXC\u断点(code=EXC\u I386\u BPT,subcode=0x0)
*帧0:0x00000001018527ad libswiftCore.dylib`swift\u dynamicCast+1229
帧#1:0x000000010d6c3a09$uu lldb_expr248`uu lldb_expr_248; 248.vec_点(a=0x00007fff5e5a9648处的Swift.Array,b=0x00007fff5e5a9640处的Swift.Array)->操场248处的Swift.Double+921。Swift:54
帧#2:0x000000010d6c15b0$u lldb_expr248 `游戏场顶级代码+1456 248。swift:64
帧#3:0x000000010d6c4561$uu lldb_expr248`main+49 at:0
帧#4:0x000000010165b390 FirstTestPlayed`get_field_types_uuuuxCPappdelegate+160
帧#5:0x000000010165bea1 FirstTestPlayed `从@callee_owned()->(@unowned())到@callee_owned(@in())->(@out())+17的重分离thunk helper
帧#6:0x000000010165ab61 FirstTestPlayed `部分应用转发器重新提取从@callee_owned()->(@unowned())到@callee_owned(@in())->(@out())+81的thunk helper
帧#7:0x000000010165bed0 FirstTestPlayed `从@callee_owned(@in())->(@out())到@callee_owned()->(@unowned())+32的重新提取thunk helper
帧#8:0x000000010165bf07 FirstTestPlayed `从@callee_owned()->(@unowned())到@callee_unowned@objc_block()->(@unowned())+39的重分离thunk helper
帧#9:0x0000000101FEDAC CoreFoundation`\uuuu CFRUNLOOP\u正在调用\u OUT\u到\u块\uuu+12
帧#10:0x0000000101fe37f5 CoreFoundation`\uU CFRunLoopDoBlocks+341
帧#11:0x0000000101fe2fb3 CoreFoundation`\uu CFRunLoopRun+851
帧#12:0x0000000101fe29f6 CoreFoundation`CFRunLoopRunSpecific+470
帧#13:0x000000010208f2b1 CoreFoundation`CFRunLoopRun+97
帧#14:0x0000000101658be8 FirstTestPlayed`顶层代码+3784
帧#15:0x000000010165b3ba第一测试场`主+42
帧#16:0x0000000103cd9145 libdyld.dylib`start+1
我尝试了不同的角色:
let x = Double(a[i] * b[1])
错误:找不到接受提供的参数的“init”的重载
错误:无法使用类型为“T”的参数调用“init”
接下来,我尝试:
let y = Double(a[i]) * Double(b[1])
let x = y
错误:无法使用类型为“(Double,Double”)的参数列表调用“*”
我尝试了更多的东西。只要我尝试将Int
作为泛型类型传递,就什么都不起作用了
也许我只是缺少了一些基本的东西,或者我太笨了,不懂泛型编程。在C++中,我将在2秒内完成。< p>当用<代码> int 数组调用时,<代码> A[i] *b[i] < /C> >是<代码> int <代码>,不能被强制转换
使用as
加倍
为了解决这个问题,您可以更改vec_dot
函数以返回T
对象,而不是一个Double
。
要使初始化var s:T=0
工作,必须使summablemplicatable
源自IntegerLiteralConvertible
(已符合Int
和Double
的要求):
或者,如果向量积始终应产生一个双精度
,则可以
将doubleValue()
方法添加到summableMultipulable
协议:
protocol SummableMultipliable: Equatable {
func +(lhs: Self, rhs: Self) -> Self
func *(lhs: Self, rhs: Self) -> Self
func doubleValue() -> Double
}
extension Double: SummableMultipliable {
func doubleValue() -> Double { return self }
}
extension Int : SummableMultipliable {
func doubleValue() -> Double { return Double(self) }
}
func vec_dot<T where T: SummableMultipliable>(a : [T], b: [T]) -> Double {
assert(a.count == b.count, "vectors must be of same length")
var s : Double = 0
for var i = 0; i < a.count; ++i {
let x = (a[i] * b[i]).doubleValue()
s = s + x
}
return s
}
正如您可能已经注意到的那样,例外的原因是悲观情绪。公平地说,您试图做的是非法的,编译器一开始就不应该允许您这么做
由于vec_dot
只知道T
是summablemployable
,它不能像那样将其转换为Double
(它如何知道它不是字符串?)
解决此问题的简单方法是,摆脱通用约束,改用函数重载:
func vec_dot(a: [Double], b: [Double]) -> Double {
assert(a.count == b.count, "vectors must be of same length")
var s: Double = 0.0
for i in 0 ..< a.count {
let x = (a[i] * b[i])
s += x
}
return s
}
func vec_dot(a: [Int], b: [Int]) -> Double {
return vec_dot(a.map({ Double($0) }), b.map({ Double($0) }))
}
var doubleVec: [Double] = [1, 2, 3, 4]
vec_dot(doubleVec, doubleVec) // 30.0
var intVec: [Int] = [1, 2, 3, 4]
vec_dot(intVec, intVec) // 30.0
func向量点(a:[Double],b:[Double])->Double{
断言(a.count==b.count,“向量必须具有相同的长度”)
变量s:Double=0.0
对于0中的i..Double{
返回向量点(a.map({Double($0)}),b.map({Double($0)}))
}
var doubleVec:[Double]=[1,2,3,4]
vec_点(doubleVec,doubleVec)//30.0
var intVec:[Int]=[1,2,3,4]
vec_点(intVec,intVec)//30.0
如果您仍然想坚持使用协议和泛型,请参阅。作为一个小补充,我还建议使用for I in 0..
而不是类似c的语法。回答得好。谢谢。我喜欢最后一个有拉链的。不知道Swift是如此受函数式编程的启发。小注:你的vec_点(intVec,intVec)
返回一个双精度(30.0),而不是一个Int,正如注释所暗示的那样。
let y = Double(a[i]) * Double(b[1])
let x = y
protocol SummableMultipliable: Equatable, IntegerLiteralConvertible {
func +(lhs: Self, rhs: Self) -> Self
func *(lhs: Self, rhs: Self) -> Self
}
func vec_dot<T where T: SummableMultipliable>(a : [T], b: [T]) -> T {
assert(a.count == b.count, "vectors must be of same length")
var s : T = 0
for var i = 0; i < a.count; ++i {
let x = (a[i] * b[i])
s = s + x
}
return s
}
var doubleVec : [Double] = [1,2,3,4]
let x = vec_dot(doubleVec, doubleVec)
println(x) // 30.0 (Double)
var intVec : [Int] = [1,2,3,4]
let y = vec_dot(intVec, intVec)
println(y) // 30 (Int)
protocol SummableMultipliable: Equatable {
func +(lhs: Self, rhs: Self) -> Self
func *(lhs: Self, rhs: Self) -> Self
func doubleValue() -> Double
}
extension Double: SummableMultipliable {
func doubleValue() -> Double { return self }
}
extension Int : SummableMultipliable {
func doubleValue() -> Double { return Double(self) }
}
func vec_dot<T where T: SummableMultipliable>(a : [T], b: [T]) -> Double {
assert(a.count == b.count, "vectors must be of same length")
var s : Double = 0
for var i = 0; i < a.count; ++i {
let x = (a[i] * b[i]).doubleValue()
s = s + x
}
return s
}
for i in 0 ..< a.count { ... }
let s : T = reduce(Zip2(a, b), 0) { $0 + $1.0 * $1.1 }
func vec_dot(a: [Double], b: [Double]) -> Double {
assert(a.count == b.count, "vectors must be of same length")
var s: Double = 0.0
for i in 0 ..< a.count {
let x = (a[i] * b[i])
s += x
}
return s
}
func vec_dot(a: [Int], b: [Int]) -> Double {
return vec_dot(a.map({ Double($0) }), b.map({ Double($0) }))
}
var doubleVec: [Double] = [1, 2, 3, 4]
vec_dot(doubleVec, doubleVec) // 30.0
var intVec: [Int] = [1, 2, 3, 4]
vec_dot(intVec, intVec) // 30.0