2015-09-17 21:12:39 +03:00
|
|
|
public enum Stream<A>: NilLiteralConvertible, SequenceType {
|
2015-09-16 18:42:49 +03:00
|
|
|
case Nil
|
2015-09-16 21:56:34 +03:00
|
|
|
indirect case Cons(A, Memo<Stream>)
|
2015-09-16 18:44:56 +03:00
|
|
|
|
2015-09-16 18:54:19 +03:00
|
|
|
public init<S: SequenceType where S.Generator.Element == A>(sequence: S) {
|
|
|
|
self = Stream(generator: sequence.generate())
|
|
|
|
}
|
|
|
|
|
|
|
|
public init<G: GeneratorType where G.Element == A>(var generator: G) {
|
|
|
|
self = Stream { generator.next() }
|
|
|
|
}
|
|
|
|
|
|
|
|
public init(_ f: () -> A?) {
|
2015-09-16 20:44:02 +03:00
|
|
|
self = f().map { Stream.Cons($0, Memo { Stream(f) }) } ?? Stream.Nil
|
2015-09-16 18:54:19 +03:00
|
|
|
}
|
|
|
|
|
2015-09-17 21:23:33 +03:00
|
|
|
public func analysis<B>(@noescape ifCons ifCons: (A, Memo<Stream>) -> B, @noescape ifNil: () -> B) -> B {
|
|
|
|
switch self {
|
|
|
|
case let .Cons(first, rest):
|
|
|
|
return ifCons(first, rest)
|
|
|
|
case .Nil:
|
|
|
|
return ifNil()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-17 21:22:05 +03:00
|
|
|
public var uncons: (first: A, rest: Memo<Stream>)? {
|
|
|
|
return analysis(ifCons: { $0 }, ifNil: { nil })
|
2015-09-16 18:44:56 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
public var first: A? {
|
|
|
|
return uncons?.first
|
|
|
|
}
|
|
|
|
|
2015-09-17 21:26:25 +03:00
|
|
|
public var rest: Memo<Stream> {
|
|
|
|
return analysis(ifCons: { $1 }, ifNil: { Memo(evaluated: .Nil) })
|
2015-09-16 18:44:56 +03:00
|
|
|
}
|
2015-09-16 18:56:06 +03:00
|
|
|
|
|
|
|
public var isEmpty: Bool {
|
|
|
|
return uncons == nil
|
|
|
|
}
|
2015-09-16 19:27:23 +03:00
|
|
|
|
|
|
|
|
|
|
|
public func map<B>(transform: A -> B) -> Stream<B> {
|
2015-09-16 20:44:02 +03:00
|
|
|
return uncons.map { first, rest in Stream<B>.Cons(transform(first), Memo { rest.map(transform) }) } ?? Stream<B>.Nil
|
2015-09-16 19:27:23 +03:00
|
|
|
}
|
2015-09-16 19:28:45 +03:00
|
|
|
|
|
|
|
|
2015-09-17 21:14:01 +03:00
|
|
|
public func concat(other: Stream) -> Stream {
|
|
|
|
switch self {
|
|
|
|
case .Nil:
|
|
|
|
return other
|
|
|
|
case let .Cons(first, rest):
|
|
|
|
return .Cons(first, rest.map { $0.concat(other) })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-09-17 21:12:39 +03:00
|
|
|
public init(nilLiteral: ()) {
|
|
|
|
self = .Nil
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-09-16 19:28:45 +03:00
|
|
|
public func generate() -> AnyGenerator<A> {
|
|
|
|
var current = self
|
|
|
|
return anyGenerator {
|
|
|
|
let next = current.first
|
|
|
|
current = current.rest
|
|
|
|
return next
|
|
|
|
}
|
|
|
|
}
|
2015-09-16 18:42:49 +03:00
|
|
|
}
|