swift - 是否可以在 Swift 中创建 "Positive Number"类型?

标签 swift types static-analysis

抱歉,如果这是一个愚蠢的问题,但我想知道 Swift 中是否有一种方法可以创建一种专门保存严格大于零的数字的类型,并且在编译时强制执行值的“正数”。

例如,我可以以某种方式编写类似的代码

func divide(x: PositiveNumber, y: PositiveNumber){
    return x / y
}

这样

divide(1, 3)

有效,但是

divide(1, 0)

无法编译?

我能想到的最接近的东西是一个只有一个容易出错的初始值设定项的结构,这样该类型要么具有正值,要么为零:

struct PositiveNumber {
    let value: Float

    init?(value: Float){
        if value > 0 {
            self.value = value
        } else {
            return nil
        }
    }
}

func / (left: PositiveNumber, right: PositiveNumber) -> Float {
    return left.value / right.value
}

func divide(x: PositiveNumber?, y: PositiveNumber?) -> Float? {
    if let x = x, y = y {
        return x / y
    }
    return nil
}

let x1 = PositiveNumber(value: 1)
let y1 = PositiveNumber(value: 3)

let x2 = PositiveNumber(value: -1)
let y2 = PositiveNumber(value: 0)

divide(x1, y: y1)!  // .333
divide(x2, y: y2)!  // runtime error

这并不可怕,但我们仍然需要处理很多可选的处理/展开。我问这个问题是因为我的代码中有很多地方需要检查值是否不为零,并且我很好奇是否有办法删除该代码并让编译器处理它。基于结构的解决方案需要几乎相同数量的代码。

最佳答案

Number Type build on Float

这个要点包含一个结构,它几乎也符合 Float 所符合的所有内容。它只是 Float 的普通副本,根据您的喜好进行更改。

<小时/>

您考虑过自定义运算符吗?

infix operator /+ { associativity left precedence 150 }

func /+(lhs:Float,rhs:Float) -> Float? {

    guard rhs > 0 else {
        return nil
    }
    return lhs / rhs
}

let test = 2 /+ -1 // nil
let test2 = 2 /+ 1 // 2

let test3 = 2 /+ 1 + 2 // warning

是否让它返回一个可选值、一个枚举值或不同的协议(protocol)并不重要。您必须处理返回。但这样你会收到编译器警告。

<小时/>

仅用一个运算符来处理除法的有限数字类型:

您可以完全更改数学并创建一个 PositiveNumber 类型,该类型在除以小于零的值时返回 NaN。

public struct PositiveFloat {
    public var value: Float
    /// Create an instance initialized to zero.
    public init() {
        self.value = 0
    }
    /// Create an instance initialized to `value`.
    public init(_ value: Float) {
        self.value = value
    }

    public init(_ value: PositiveFloat) {
        self.value = value.value
    }
}

extension Float {
    public var positive : PositiveFloat {
        return PositiveFloat(self)
    }
}


public func /(lhs:Float,rhs:PositiveFloat) -> Float {
    if 0 > rhs.value {
        return lhs / rhs.value
    } else {
        return Float.NaN
    }
}
public func /(lhs:PositiveFloat,rhs:PositiveFloat) -> Float {
    if 0 > rhs.value {
        return lhs.value / rhs.value
    } else {
        return Float.NaN
    }
}
<小时/>
let testNormal : Float = 10
let testFloat : Float = -5

let test = testFloat / testNormal.positive
if test.isNaN {
    // do stuff
}

关于swift - 是否可以在 Swift 中创建 "Positive Number"类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34260199/

相关文章:

ios - 避免 swift 覆盖本地通知

swift - IOS PDFKit - 注释内容仅在选中时可见

swift - 如何使用 SpriteKit swift 重新着色 Sprite

c - 定义用于多个文件的枚举数据类型

typescript - TypeScript JSDoc 样式的类型是否具有常规类型的全部功能?

python - "MetaClass"、 "__new__"、 "cls"和 "super"- 究竟是什么机制?

ruby-on-rails - 有没有可以比较或解析多种语言的工具?

ios - 支持 iOS 8 - swift

c++ - 用于模型检查大型分布式 C++ 项目(如 KDE)的工具?

java - 可能会抛出 "NullPointerException"; "context"在这里可以为空