-
-
Save tototoshi/3120089 to your computer and use it in GitHub Desktop.
// import scala.collection.JavaConversions._ | |
scala> val git = new Git(new FileRepositoryBuilder().findGitDir(new java.io.File("/path/to/repos")).readEnvironment().build()) | |
git: org.eclipse.jgit.api.Git = org.eclipse.jgit.api.Git@18ed36fb | |
scala> git.log.addPath("foo").call.head | |
res49: org.eclipse.jgit.revwalk.RevCommit = commit c4554d9f46de49e449242a2aa75d39874dc99498 1342332998 ----sp | |
scala> git.log.addPath("foo").call.headOption | |
res50: Option[org.eclipse.jgit.revwalk.RevCommit] = Some(commit d3107ef998b25d70f86f1a5d530c31c02507d59e 1342012813 ----sp) | |
scala> git.log.addPath("foo").call.toList.head | |
res51: org.eclipse.jgit.revwalk.RevCommit = commit c4554d9f46de49e449242a2aa75d39874dc99498 1342332998 ----sp | |
scala> git.log.addPath("foo").call.toList.headOption | |
res52: Option[org.eclipse.jgit.revwalk.RevCommit] = Some(commit c4554d9f46de49e449242a2aa75d39874dc99498 1342332998 ----sp) | |
scala> git.log.addPath("foo").call.toList | |
res53: List[org.eclipse.jgit.revwalk.RevCommit] = List(commit c4554d9f46de49e449242a2aa75d39874dc99498 1342332998 ----sp, commit d3107ef998b25d70f86f1a5d530c31c02507d59e 1342012813 ----sp) | |
// headOption fetches second element?? |
https://github.com/scala/scala/blob/v2.9.2/src/library/scala/collection/JavaConversions.scala#L401
https://github.com/scala/scala/blob/v2.9.2/src/library/scala/collection/JavaConversions.scala#L587
JIterableWrapper
がつくられる
https://github.com/scala/scala/blob/v2.9.2/src/library/scala/collection/TraversableLike.scala#L422
isEmpty
が呼ばれる
https://github.com/scala/scala/blob/v2.9.2/src/library/scala/collection/IterableLike.scala#L81-82
https://github.com/scala/scala/blob/v2.9.2/src/library/scala/collection/IterableLike.scala#L63
isEmpty
のために新しいiteratorがつくられる(そのiteratorが先頭の要素保持しちゃう)
head
呼ぶ
https://github.com/scala/scala/blob/v2.9.2/src/library/scala/collection/IterableLike.scala#L72
head
の中で呼ばれる foreach
も新しいIterator生成するが、 isEmpty
のときに生成した Iterator が先頭の要素を保持というか消費してて、二回目にここで生成したiteratorは、2番目の要素が先頭になってる
call
が返す、java.lang.Iterable
型のオブジェクトのiterator
のメソッドの実装がiterator
というメソッドを呼ぶ度に毎回新しいIteratorを生成して返すのではなく、
call
が返したIterable
型のオブジェクトからは、1度しかiteratorメソッドを呼べない (複数回呼んでも、すでに中途半端に消費されたIteratorが返ってくる可能性あり)っていう実装になってるみたい。
scala側は、毎回新しいIteratorが返る ことを前提で実装してるのでこうなる。
これが一般的に java での Itetable や Iterator の規約違反なのかどうかはしらぬ・・・(まぁなんか個人的にはおかしい気がするけど)
http://java.sun.com/javase/ja/6/docs/ja/api/java/lang/Iterable.html
言い換えると、ある意味、
call
が返すjava.lang.Iterable
型のオブジェクト自体が状態を持ってるjgit の javadoc にはそれが書いてあるのか・・・
https://github.com/eclipse/jgit/blob/aeb28b1f3e8763c006dd26e690fbcad0920bc1a4/org.eclipse.jgit/src/org/eclipse/jgit/api/LogCommand.java#L105-109
だったらこれ、もう最初から Iterator 返せばいいのに・・・