[英]Swift, math functions and protocols
我正在嘗試創建2個協議ArithmeticType和MathematicType,它們將用於泛型運算符函數的where子句
protocol ArithmeticType {
func +(lhs: Self, rhs: Self) -> Self
func -(lhs: Self, rhs: Self) -> Self
func *(lhs: Self, rhs: Self) -> Self
func /(lhs: Self, rhs: Self) -> Self
}
extension Int : ArithmeticType {
}
extension Double : ArithmeticType {
}
extension Float : ArithmeticType {
}
ArithmeticType按預期工作,Int,Float和Double符合它。 但是以下失敗了
import Darwin
protocol MathematicType {
func sin(x: Self) -> Self
}
extension Double : MathematicType {
}
extension Float : MathematicType {
}
我在游樂場的控制台輸出上讀到:
Playground execution failed: <EXPR>:35:1: error: type 'Double' does not conform to protocol 'MathematicType'
extension Double : MathematicType {
^
<EXPR>:32:10: note: protocol requires function 'sin' with type 'Double -> Self'
func sin(x: Self) -> Self
^
<EXPR>:39:1: error: type 'Float' does not conform to protocol 'MathematicType'
extension Float : MathematicType {
^
<EXPR>:32:10: note: protocol requires function 'sin' with type 'Float -> Self'
func sin(x: Self) -> Self
^
我希望數學函數的行為與上面的運算符相似。 有什么辦法嗎?
==編輯:
現在我意識到試圖簡化我的問題是一個壞主意。 上下文是這個類(可選值的向量)
class Vector<T> {
var data=[T?]()
init(fromArray: Array<T>) {
for i in fromArray {
data.append(i)
}
}
init() {
}
init(count: Int){
for i in 0..<count {
data.append(nil)
}
}
init(count: Int, repeatedValue: T) {
for i in 0..<count {
data.append(repeatedValue)
}
}
func count() -> Int {
return data.count
}
func append(newElement: T?) {
data.append(newElement)
}
subscript(index: Int) -> T? {
let i = index>0 ? index % count() : -index % count()
return data[i]
}
}
在它之外我為+運算符定義了一個通用函數
func +<T where T: ArithmeticType>(left: Vector<T>, right: Vector<T>) -> Vector<T> {
let resultCount = max(left.count(),right.count())
var result = Vector<T>()
for i in 0..<resultCount {
if left[i] != nil && right[i] != nil {
result.append(left[i]!+right[i]!)
}
else {
result.append(nil)
}
}
return result
}
這是按預期工作的,但是當我試圖將一般的sin函數定義為
func sin<T where T : FloatingPointType>(x: Vector<T>) -> Vector<T>{
var result = Vector<T>()
for i in 0..<x.count() {
if let o = x[i] {
result.append(sin(o))
}
else {
result.append(nil)
}
}
return result
}
我得到“找不到接受提供的參數的罪的重載”
然后我嘗試使用MathemticType試圖模仿我已經為+運算符所做的事情
(ArithmeticType的靈感來自IntegerAritmeticType源,通過命令點擊導入swift找到的比我對我正在做的事情的了解更多)
==更新
如果我只為Double編寫一個專門的函數
func sin(x: Vector<Double>) -> Vector<Double>{
var result = Vector<Double>()
for i in 0..<x.count() {
if let o = x[i] {
result.append(Darwin.sin(o))
}
else {
result.append(nil)
}
}
return result
}
它按預期工作。
所以這個問題可能會成為“我如何將其概括為Double和Float”?
編譯器錯誤是因為您將sin()
聲明為MathematicType
協議的方法,然后聲明Double
實現了MathematicType
,但實際上並沒有編寫sin()
方法。
extension Double {
func sin(x: Double) -> Double {
return Darwin.sin(x)
}
}
我認為這不是你想要的,不是嗎? 你希望能夠寫下這個:
let myAngle = 3.14159
let sineValue = myAngle.sin()
如果是這種情況,您的協議和擴展將需要如下所示:
protocol MathematicType {
func sin() -> Self
}
extension Double : MathematicType {
func sin() -> Double {
return Darwin.sin(self)
}
}
你的MathematicType
協議,以及你在Float
和Double
擴展中對它的一致性聲明,說Float
和Double
應該提供sin
作為實例方法。 也就是說,你說應該能夠編寫如下代碼:
let zero = 0.0 // inferred type Double
zero.sin(1.5707963268) // returns about 1.0
請注意,調用sin
實際上並不與zero
值相關,因此這可能不是您想要的行為。
你可能希望sin
是一個自由函數,所以你可以寫:
sin(1.5707963268)
對?
在這種情況下,您的工作已經完成......標准庫定義了兩個:
func sin(x: Double) -> Double
func sin(x: Float) -> Float
如果你真正想要的是你的MathematicType
可用作泛型參數,意思是“你可以采用正弦的類型”,你需要一個通用的sin
函數。 像這樣的東西(快速kludgy解決方案,可能更好):
func sine<T: FloatingPointType>(x: T) -> T {
if let v = x as? Double {
return sin(v) as T
}
if let v = x as? Float {
return sin(v) as T
}
fatalError("unknown FloatingPointType")
}
(另請注意,已經存在Float
和Double
符合的協議,因此我在示例中使用了該協議。)
我認為問題是運算符要求和實例方法要求是不同的,即使它們在語法上看起來相似。 運營商始終在全球范圍內定義,因此運營商要求是全球運營商的要求。 另一方面,實例方法要求是實例方法的要求。 無法指定全局功能要求。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.