使用协议作为类型必须与任何(学习目的)一起编写

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

我已将代码从函数式编程语言翻译为 Swift,并且在通过变量进行验证时效果很好。但是,我在测试时遇到错误,原因是 Streamable 和任何 Streamable 不兼容。这是上下文:

Streamable 协议充当泛型或声明符合协议的变量的类型约束。相反,任何 Streamable 都表示符合 Streamable 的类型,在闭包中用于捕获或返回此类类型。

如何利用 Streamable 来实现unnyNumberStream?

顺便说一句,我让它变得如此简单易懂,所以应该不难理解。

protocol Streamable {
    associatedtype Element
    func next() -> (Element, Self)
}

struct OnesStream: Streamable {
    func next() -> (Int, OnesStream) {
        return (1, OnesStream())
    }
}

final class LazyNaturalStream: Streamable {
    private var current: Int
    
    init(start: Int = 1) {
        self.current = start
    }
    
    func next() -> (Int, LazyNaturalStream) {
        let result = current
        current += 1
        return (result, LazyNaturalStream(start: current))
    }
}

func streamForNSteps<S: Streamable>(_ s: S, _ n: Int) -> [S.Element] {
    if n == 0 {
        return []
    } else {
        let next = s.next()
        return [next.0] + streamForNSteps(next.1, n - 1)
    }
}

let globalLazyNaturalStream = LazyNaturalStream()

let funnyNumberStream: any Streamable = {
    struct FunnyStream: Streamable {
        var localLazyNaturalStream = globalLazyNaturalStream
        
        func next() -> (Int, FunnyStream) {
            let currentValue = localLazyNaturalStream.next()
            
            if currentValue.0 % 5 == 0 {
                return (-currentValue.0, FunnyStream(localLazyNaturalStream: currentValue.1))
            } else {
                return (currentValue.0, FunnyStream(localLazyNaturalStream: currentValue.1))
            }
        }
    }
    
    return FunnyStream()
}()

// Example usage
// [1, 2, 3, 4, -5, 6, 7, 8, 9, -10, 11, 12, 13, 14, -15, 16]
let a = streamForNSteps(funnyNumberStream, 16)

上面的示例工作得很好,测试用例才是问题所在。

测试用例:

final class hw4Test: XCTestCase {
    
    func testFunnyNumberStream() throws {
        // Act
        let caseOneResult = streamForNSteps(funnyNumberStream, 0)
        let caseTwoResult = streamForNSteps(funnyNumberStream, 16)
        let caseThreeResult = streamForNSteps(funnyNumberStream, 5)
        
        // Assert
        XCTAssertEqual(caseOneResult, []) // Type 'Any' cannot conform to 'Equatable'
        XCTAssertEqual(caseTwoResult, [1, 2, 3, 4, -5, 6, 7, 8, 9, -10, 11, 12, 13, 14, -15, 16]) // Type 'Any' cannot conform to 'Equatable'
        XCTAssertEqual(caseThreeResult, [1, 2, 3, 4, -5]) // Type 'Any' cannot conform to 'Equatable'
    }
}

欢迎任何解释!!!

swift types protocols
1个回答
0
投票
let funnyNumberStream: any Streamable = { ... }

这表明

funnyNumberStream
不仅可以由任何
Streamable
类型实现,而且可以由任何
Streamable
类型实现任何
Element
类型。你的意思似乎是它应该是
Int
的流。这最容易用主要关联类型来表达:

protocol Streamable<Element> {  // <--- Add <Element> as the primary associated type
    associatedtype Element
    func next() -> (Element, Self)
}

然后您可以将变量限制为返回

Streamable
Int
:

let funnyNumberStream: any Streamable<Int> = { ... }
© www.soinside.com 2019 - 2024. All rights reserved.