IterV
IterVはIterateeです。
ストリームをイテレートするものと考えて下さい。
ストリームを表すものとしてEnumeratorが定義されています。
IterV#applyによりEnumeratorをイテレートし、IterV#runで実行されます。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import IterV._ | |
implicit lazy val StreamEnumerator: Enumerator[Stream] = new Enumerator[Stream] { | |
def apply[E, A](e: Stream[E], i: IterV[E, A]): IterV[E, A] = e match { | |
case Stream() => i | |
case x #:: xs => i.fold(done = (_, _) => i, cont = k => apply(xs, k(El(x)))) | |
} | |
} | |
head(Stream(3, 4, 6)).run assert_=== Some(3) |
Enumerator#applyはコンテナとIterVをとり、コンテナをイテレートする関数が定義されます。
IterV#foldは、計算が終了した場合は結果と入力をとり、計算が途中の場合は入力から次の計算を取り出す関数をとり、何らかの値を返します。
入力にはEmpty, El, EOFがあり、それぞれデータなし、データあり、データの終わりを表します。
IterVには標準でいくつかの操作が定義されています。
IterV.head
ストリームを消費して、先頭要素をOptionで返します。
IterV.peek
先頭要素を返します。
こちらはストリームを消費しません。
IterV.length
ストリームの長さを取得します。
IterV.drop
指定した数だけストリームを消費します。
IterV.collect
指定した型に変換します。
IterV.groupBy
先頭要素と各要素をとる述語が真である限り、要素を集めます。
IterV.takeWhile
述語が真のあいだ、要素を集めます。
IterV.reversed
要素の順序を逆にしたコンテナを返します。
IterV.repeat
Iterateeを繰り返し、結果を集めます。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
head(Stream(1, 2, 3)).run assert_=== Some(1) | |
peek(Stream(1, 2, 3)).run assert_=== Some(1) | |
length(Stream(1, 2, 3)).run assert_=== 3 | |
drop(2)(Stream(1, 2, 3)).run assert_=== () | |
collect[Int, List].apply(Stream(1, 2, 3)).run assert_=== List(1, 2, 3) | |
groupBy[Int, List](_ === _).apply(Stream(1, 1, 2, 1, 1, 2)).run assert_=== List(1, 1) | |
takeWhile[Int, List](_ % 2 === 0).apply(Stream(2, 4, 5, 6)).run assert_=== List(2, 4) | |
reversed[Int, List](ListReducer)(Stream(1, 2, 3)).run assert_=== List(3, 2, 1) | |
repeat[Int, List[Int], List](groupBy[Int, List](_ === _)).apply(Stream(1, 1, 2, 1, 1, 2)).run assert_=== List(List(1, 1), List(2), List(1, 1), List(2)) | |
peekDoneOr[Int, List[Int]](5.pure[List], i => takeWhile(_ lt 3))(Stream(1, 2, 3)).run assert_=== List(1, 2) |
そして、Iterateeは合成が可能です。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(drop[Int](2) >|> length).apply(Stream(1, 2, 3)).run assert_=== 1 | |
(drop[Int](1) >|> collect[Int, List]).apply(Stream(1, 2, 3)).run assert_=== List(2, 3) | |
(head[Int] >>= (o => head.map(_ |+| o))).apply(Stream(1, 5, 3)).run assert_=== Some(6) |
scalaz.effectsパッケージではIterateeを使った入力ストリームがあります。
あまり詳しく書いていませんが、Scalaz.effectsについてを書いたので興味があったら見てください。
いまではWeb FrameworkのPlay!にも存在します。
http://playframework.github.com/api/scala/#play.api.libs.iteratee.package
今後の入出力操作の標準となるかもしれないので勉強しておいて損はないはずです。
scalaquery にもあるよ!
返信削除https://github.com/szeiger/scala-query/blob/0.9.5/src/main/scala/org/scalaquery/iter/Iteratee.scala#L9
おお、知りませんでした。
返信削除すでに乱立しているかもしれないけど、Scalaz7でみなが使わざるおえない出来になることを期待しています。