将泛型返回其离散类型

问题描述 投票:0回答:1

我使用 DecimalDouble 进行了一系列计算。如果没有泛型,就会有很多重复的代码。有些地方我最终需要更原生格式的十进制,但我似乎不知道如何在 Swift 中做到这一点。

一个假设的例子:Decimal中没有log2(),但由于可接受的误差范围,我想将其转换为Double并以这种方式使用它。

最初我以为我只是创建一个适用于 DoubleDecimal

的通用函数
// Dtype is either Decimal or Double
typealias Dtype =  SignedNumeric

func mylog2<T: Dtype>(_ x: T) -> Double
{
    let x_double: Double = Double(truncating: x as NSNumber) //'T' is not convertible to 'NSNumber'
    return log2(x_double)
}

但是我得到了一个错误,所以我想我只需将它们分成离散函数即可。经过思考,我认为 T 无法暴露其实际类型。然后我想我应该将函数拆分为离散类型并尝试以这种方式使用它:

func mylog2(_ x: Decimal) -> Double
{
    let x_double: Double = Double(truncating: x as NSNumber)
    return log2(x_double)
}

func mylog2(_ x: Double) -> Double
{
    return log2(x)
}

但是我不知道如何让 T 通过离散类型使用 mylog2() 函数:

func myExample<T: Dtype>(_ a: T, _ b: T) -> Double
{
    let c: T = (a + b) * (b - a)
    //bunch of other maths funcs
    return mylog2(c) //No exact matches in call to global function 'mylog2'
}

我很确定在其他语言中也有办法处理这样的情况,所以一定有办法。我可能用不正确的 Swift 思维方式来解决这个问题,并且有一种完全不同的方式,我不知道如何做到这一点。无论如何,如果有人可以帮助我快速解决这个问题,我将不胜感激。

swift macos generics decimal
1个回答
0
投票

只需声明您自己的协议,需要实现

log2
方法。
Double
Decimal
均符合此协议。

protocol Log2 {
    func log2() -> Double
}

extension Decimal: Log2 {
    func log2() -> Double {
        Darwin.log2(Double(truncating: self as NSNumber))
    }
}

extension Double: Log2 {
    func log2() -> Double {
        Darwin.log2(self)
    }
}

然后您可以将泛型类型参数约束为

Log2 & SignedNumeric

typealias Dtype = SignedNumeric & Log2

func myExample<T: Dtype>(_ a: T, _ b: T) -> Double
{
    let c: T = (a + b) * (b - a)
    //bunch of other maths funcs
    return c.log2()
}
© www.soinside.com 2019 - 2024. All rights reserved.