I've translated code from a functional programming language to Swift, and it works well when verifying via variables. However, I encounter an error when testing, attributed to Streamable and any Streamable incompatibility. Here's the context:
The Streamable protocol acts as a type constraint for generics or for declaring protocol-conforming variables. Conversely, any Streamable signifies a type conforming to Streamable, used in closures to capture or return such types.
How can I utilize Streamable for funnyNumberStream?
Btw I made it so simple to follow, so should not be hard to understand.
protocol Streamable {
associatedtype Element
func next() -> (Element, Self)
}
struct OnesStream: Streamable {
func next() -> (Int, OnesStream) {
return (1, OnesStream())
}
}
struct LazyNaturalStream: Streamable {
private var current: Int
init(start: Int = 1) {
self.current = start
}
func next() -> (Int, LazyNaturalStream) {
let result = current
return (result, LazyNaturalStream(start: current + 1))
}
}
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 funnyNumberStream: any Streamable = {
struct FunnyStream: Streamable {
var localLazyNaturalStream = LazyNaturalStream()
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)
The example from above it works perfectly fine, the test cases are the problem.
Test Cases:
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'
}
}
Any explanation is welcomed!!!
let funnyNumberStream: any Streamable = { ... }
This indicates that funnyNumberStream
not only can be implemented by any Streamable
type, but any Streamable
type for any Element
type. What you seem to mean is that it is supposed to be a stream of Int
. That is most easily expressed with a primary associated type:
protocol Streamable<Element> { // <--- Add <Element> as the primary associated type
associatedtype Element
func next() -> (Element, Self)
}
And then you can constrain your variable to a Streamable
that returns Int
:
let funnyNumberStream: any Streamable<Int> = { ... }