在 Swift 函数中处理动态输出而不牺牲类型安全

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

我在 Swift 中有一个基本的自定义结构,由于语言的静态类型性质,使用

Any
作为输入类型不太理想,这可以绕过编译器的类型检查并导致错误和类型信息丢失。

但是,我遇到了需要从

Any
等函数返回
vectorAssoc
的情况,特别是对于返回类型可以是元组或布尔值的情况。以下是
Vector
vectorAssoc
函数的示例:

struct Vector<Element>: ExpressibleByArrayLiteral {
    private var storage: [Element] = []
    
    public init(arrayLiteral elements: Element...) {
        storage = elements
    }
    
    func count() -> Int {
        return storage.count
    }
    
    subscript(index: Int) -> Element {
        return storage[index]
    }
}

func vectorAssoc(_ v: Int, _ vec: Vector<(Int, Int)>) -> Any {
    func helper(_ i: Int) -> Any {
        if i >= vec.count() {
            return false
        } else {
            let elem = vec[i]
            
            if elem.0 == v {
                return elem
            } else {
                return helper(i + 1)
            }
        }
    }
    
    return helper(0)
}

let vec: Vector = [(2, 1), (3, 1), (4, 1), (5, 1)]

// Example usage
let a = vectorAssoc(4, vec) // prints (4, 1)
let b = vectorAssoc(12, vec) // prints false

由于

vectorAssoc
的输出可以用作另一个函数的输入,我正在寻求有关如何更有效地处理返回类型
Any
的建议。理想情况下,我正在寻找一种方法来指定返回类型只能是两种特定类型(元组或布尔值)之一,而不求助于自定义类型或选项。

如果有一种方法可以将这样的

Any
转换为利用 Swift 类型安全功能的原始类型,我将非常感谢对此设置的任何见解或改进。

---
所以对新问题的一个非常基本的解释是:

在这种情况下,Any 只有 2 种类型(元组和布尔值),不能超过两种。如果有一种方法可以返回 Any(只有两种特定类型),并且以某种方式 Any 将成为可以利用类型安全的原始类型(这两种类型之一)。有办法让这个工作吗?

swift types any dynamic-typing
1个回答
0
投票

首先,你一定注意到了,Swift 与 Python 不同,它有一个强大的类型系统,包括函数返回类型,并且不可能实现你想象的东西。但你还有其他选择。

我是否理解正确,布尔返回类型只是指示错误?如果是这样,为什么不明确抛出错误?

func vectorAssoc(_ v: Int, _ vec: Vector<(Int, Int)>) throws -> (Int, Int)

do {
    print(try vectorAssoc(4, vec))
} catch {
    print(false)
}

如果不是关于错误,而是返回一组有限选项中的一个选项,Swift 有用于此目的的枚举:

enum ReturnOption {
    case bool(value: Bool)
    case int(value: Int)
}

func vectorAssoc(_ v: Int, _ vec: Vector<(Int, Int)>) -> ReturnOption

switch  vectorAssoc(4, vec) {
    case .bool(let value),
         .int(let value):
        print(value)

如果你只想要两种状态,一个值或缺失值,Swift 有

Optional
来实现:

func vectorAssoc(_ v: Int, _ vec: Vector<(Int, Int)>) -> (Int, Int)?

if let resut = vectorAssoc(4, vec) {
    print(result)
} else {
    print(false)
}
© www.soinside.com 2019 - 2024. All rights reserved.