Merge pull request #19143 from hochgi/hochgi-19021-unfold

+str #19021 Add unfold (and variants) generators to Source
This commit is contained in:
Roland Kuhn 2015-12-14 11:43:49 +01:00
commit 5c55180327
5 changed files with 198 additions and 0 deletions

View file

@ -244,6 +244,64 @@ object Source {
shape("RepeatSource"))).mapConcat(ConstantFun.scalaIdentityFunction)
}
/**
* create a `Source` that will unfold a value of type `S` into
* a pair of the next state `S` and output elements of type `E`.
*
* for example, all the fibonacci numbers under 10M:
*
* {{{
* Source.unfold(0 1){
* case (a,_) if a > 10000000 None
* case (a,b) Some((b (a + b)) a)
* }
* }}}
*/
def unfold[S, E](s: S)(f: S Option[(S, E)]): Source[E, Unit] =
Source.fromGraph(new Unfold(s, f)).withAttributes(DefaultAttributes.unfold)
/**
* same as unfold, but uses an async function to generate the next state-element tuple.
*
* async fibonacci example:
*
* {{{
* Source.unfoldAsync(0 1){
* case (a,_) if a > 10000000 Future.successful(None)
* case (a,b) Future{
* Thread.sleep(1000)
* Some((b (a + b)) a)
* }
* }
* }}}
*/
def unfoldAsync[S, E](s: S)(f: S Future[Option[(S, E)]]): Source[E, Unit] =
Source.fromGraph(new UnfoldAsync(s, f)).withAttributes(DefaultAttributes.unfoldAsync)
/**
* simpler unfold, for infinite sequences.
*
* {{{
* Source.unfoldInf(0 1){
* case (a,b) (b (a + b)) a
* }
* }}}
*/
def unfoldInf[S, E](s: S)(f: S (S, E)): Source[E, Unit] = {
Source.fromGraph(GraphDSL.create() { implicit b
import GraphDSL.Implicits._
val uzip = b.add(UnzipWith(f))
val cnct = b.add(Concat[S]())
val init = Source.single(s)
init ~> cnct ~> uzip.in
cnct <~ uzip.out0
SourceShape(uzip.out1)
}).withAttributes(DefaultAttributes.unfoldInf)
}
/**
* A `Source` with no elements, i.e. an empty stream that is completed immediately for every connected `Sink`.
*/