如何为几种数字类型创建泛型函数?

时间:2017-05-25 18:22:23

标签: swift generics swift3

假设我有这些功能

// bar is some external function
// it has signature bar(_ number: Double) -> Double

func foo(number: Int) -> Double {
    return bar(Double(number))
}

func foo(number: Float) -> Double {
    return bar(Double(number))
}

func foo(number: Double) -> Double {
    return bar(number)
}

我想要一个通用函数:

func foo<T>(number: T) -> Double {
    return bar(Double(number))
}

但似乎编译器不喜欢这个想法:

enter image description here

如何在swift3中正确制作这些通用函数?或者这是不可能的?

2 个答案:

答案 0 :(得分:1)

你不想做的事情是不可能的,我不会想到。您可能对此感兴趣:https://gist.github.com/erica/2f6a38c844573c778b0f

导入代码后,您可以执行

func foo<T: DoubleRepresentable>(number: T) -> Double {
    return number.doubleValue
}

答案 1 :(得分:1)

就我而言,Swift和许多其他强类型语言应该真正回到数学学院并学习数论。除了内部表示(高级语言应该抽象而不是负担程序员),所有数字类型都属于一个较大的语言的子集。

为了弥补这一点,您可以创建一个能够理解&#34;#34;实数(Double)属于包含所有其他域的域。然后,您将能够定义将使用该协议接受来自较低级域的所有数字类型的函数,并使用&#34; Real&#34;处理它们。 (双)运算符将产生有效的结果(理论上)。

例如:

protocol Numeric
{
   var asDouble:Double { get }
}

extension Double:Numeric   { var asDouble:Double { return self } }
extension Int:Numeric      { var asDouble:Double { return Double(self) } }
extension Int8:Numeric     { var asDouble:Double { return Double(self) } }
extension Int16:Numeric    { var asDouble:Double { return Double(self) } }
extension Int32:Numeric    { var asDouble:Double { return Double(self) } }
extension Int64:Numeric    { var asDouble:Double { return Double(self) } }
extension UInt:Numeric     { var asDouble:Double { return Double(self) } }
extension UInt8:Numeric    { var asDouble:Double { return Double(self) } }
extension UInt16:Numeric   { var asDouble:Double { return Double(self) } }
extension UInt32:Numeric   { var asDouble:Double { return Double(self) } }
extension UInt64:Numeric   { var asDouble:Double { return Double(self) } }
extension Float:Numeric    { var asDouble:Double { return Double(self) } }
extension Float80:Numeric  { var asDouble:Double { return Double(self) } }
extension NSNumber:Numeric { var asDouble:Double { return Double(self) } }

func foo(_ number: Numeric) -> Double 
{
  return bar(number.asDouble)
}

当然,这并未考虑精度限制(例如Float vs Double),并且实际上不会处理来自较大域(无理或虚构)的数字,但是,从概念的角度来看,它将会得到无关紧要的变化。

现在,下一个繁琐的工作将是实现所有数学和赋值运算符,以便它们可以使用数字协议(但我会将其留给Apple)。