Swift的POW()函数将不接受兼作参数

问题描述:

我建立这个infix operator ^^作为替代使用pow功能:Swift的POW()函数将不接受兼作参数

infix operator ^^ { associativity left precedence 155 } 
func ^^ <T: IntegerLiteralConvertible>(left: T, right: T) -> T { 
    return pow(left as Double, right as Double) 
} 

我用IntegerLiteralConvertible协议作为用于泛型leftright类型约束,因为从我的理解this diagramm表明,它基本上包含了所有的数字类型。

为了使用pow功能我不得不垂头丧气leftrightDouble虽然,这我没有使用as操作。这不是最安全的方法,但除此之外。

在实现功能this way迅速告诉我:

<stdin>:4:12: error: cannot invoke 'pow' with an argument list of type '(Double, Double)' 
return pow(left as Double, right as Double) 
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

现在据我知道pow需要两个Double S作为参数,那么,为什么抱怨吗?

why is it complaining about this?

因为pow返回Double。并且DoubleT不相同。该错误消息是误导性的,但它的意思是“无法找到pow接受(Double, Double)并返回T型”


我认为你是在斯威夫特误解“中投”。在Swift中as不会转换数字类型。

let intVal:Int = 12 
let doubleVal:Double = intVal as Double 
//       ^[!] error: 'Int' is not convertible to 'Double' 

而且如果操作数的类型不是在编译时预测的,无效的铸造导致运行时错误:

func foo<T: IntegerLiteralConvertible>(x: T) { 
    x as Double // <-- Execution was interrupted 
} 
foo(12 as Int) 

相反,我们必须明确地“转换”他们。查看文档:Numeric Type Conversion

let intVal:Int = 12 
let doubleVal:Double = Double(intVal) 

这仅是因为Doubleinit(_ v: Int)初始化。下面的代码无法编译:

func foo<T: IntegerLiteralConvertible>(x: T) { 
    Double(x) 
// ^~~~~~~~~ [!] error: cannot invoke 'init' with an argument of type 'T' 
} 

因为Double没有init<T:IntegerLiteralConvertible>(_ val:T)初始化。

所以,如果你想使用pow(),你必须转换到TDouble参数,并将其转换DoubleT返回值。对此没有简单的解决方案。

感谢@马丁R.这是唯一的question我已发布迄今S.O.

import Cocoa 

协议

protocol Fraction { init(_ value:Double) ; var asDouble : Double { get } } 
protocol Text  { init(_ value:String) ; var asString : String { get } } 

扩展

extension String : Text  { var asString : String { return self } } 

extension Double : Fraction { var asDouble : Double { return self   } } 
extension Float : Fraction { var asDouble : Double { return Double(self) } } 
extension CGFloat : Fraction { var asDouble : Double { return Double(self) } } 

管道符^^

infix operator ^^ { associativity left precedence 170 } 
func ^^<T:IntegerType, U:IntegerType> (var base:T, var power:U) -> T { 
    if power < 0 { return 0 } 
    var result: T = 1 
    if power > 0 { 
     if power % 2 == 1 { result *= base } 
     power /= 2 
    } 
    while power > 0 { 
     base *= base 
     if power % 2 == 1 { result *= base } 
     power /= 2 
    } 
    return result 
} 
func ^^<T:Fraction, U:Fraction> (base: T, power: U) -> T { 
    return T(pow(base.asDouble, power.asDouble)) 
} 
func ^^<T:Text, U:IntegerType> (base:T, var power:U) -> T { 
    if power <= 0 { return "" as T } 
    if power == 1 { return base as T } 
    return power > 1 ? {var result = ""; for x in 1...power { result+=base.asString };return result as T}() : "" as T 
} 
func ^^<T:Text, U:Text> (base:T, var power:U) -> T { 
    return "" as T 
} 

测试

println(1 ^^ -1)    // "0"  Int 
println(1 ^^ 0)    // "1"  Int 
println(1 ^^ 1)    // "1"  Int 
println(1 ^^ 2)    // "1"  Int 

println(2 ^^ -1)    // "0"   Int 
println(2 ^^ 0)    // "1"   Int 
println(2 ^^ 1)    // "2"   Int 
println(2 ^^ 2)    // "4"   Int 
println(2 ^^ 8)    // "256"   Int 
println(2 ^^ 16)    // "65536"  Int 
println(2 ^^ 32)    // "4294967296" Int 

println(2 ^^ 62)    // "4611686018427387904" 

println(UInt(2) ^^ 8)   // "256"  UInt 
println(UInt64(2) ^^ 8)  // "256"  UInt64 
+1

多数民众赞成在类型安全再次感谢@马丁R – 2015-02-24 19:10:17

+0

http://*.com/questions/26794282/how-do-i-make-my-operator-work-with-double-and-int – 2015-02-24 19:15:02

+0

我上来了什么-投票? – 2015-02-24 19:36:28