0

I'm looking for a way to generate a scala stream (the equivalent of F#'s sequence) of this form:

let allRows resultSet : seq<Row> =
  seq {
    while resultSet.next() do
      yield new Row(resultSet)
  }

Is there any way to easily do this in scala? The only way I found involved (non-tailrecursive) recursion, which for large amounts of rows in a resultSet would mean certain stackoverflow.

Thanks

ildjarn
  • 62,044
  • 9
  • 127
  • 211
devoured elysium
  • 101,373
  • 131
  • 340
  • 557
  • Are you sure you want a Scala Stream? It keeps all results in memory after they are lazily calculated. It sounds like the F# sequence is more similar to a Scala Iterator, which lazily produces one value at a time, retaining only the current in memory. – Leif Wickland Nov 27 '15 at 02:20
  • I'm looking for the same behavior as F#'s sequences. I was under the impression that their equivalent in Scala would roughly be Streams (their contract seems to in some way imply their lazy nature). Am I wrong? – devoured elysium Nov 27 '15 at 08:10

2 Answers2

1

You can implement it like this:

 def toStream(rs:ResultSet):Stream[Row] =
   if(!rs.next) Stream.Empty
   else new Row(rs) #:: toStream(rs)

Note that since toStream is defined using def (in opposite to definition with val) this solution will no keep whole stream in memory and head of stream will be garbage collected.

Another option you can use is to define new Iterator:

def toIterator(rs:ResultSet) = new Iterator[Row] {
  override def hasNext: Boolean = rs.next()
  override def next(): Row = new Row(rs)
}
Nyavro
  • 8,806
  • 2
  • 26
  • 33
  • Hello. As stated in the OP, I'm looking for a tail-recursive solution (if some kind of recursive implementation is utilized). If I'm not mistaken, your stream solution is *not* tail-recursive and will blow up your stack for sufficiently large result sets. – devoured elysium Nov 27 '15 at 08:13
  • Streams don't need tail recursion: http://stackoverflow.com/questions/10525449/tail-recursive-bounded-stream-of-pairs-of-integers-scala – Nyavro Nov 27 '15 at 08:19
  • Ah, that's an interesting thing to know. I'll read the link you gave me and I'll get back to you tonight. – devoured elysium Nov 27 '15 at 09:02
1

Suppose you have something like

trait ResultSet {
  def next: Boolean
}

class Row(rs: ResultSet)

You can define your function as

def allRows(rs: ResultSet): Stream[Row] =
  Stream.continually(if (rs.next) Some(new Row(rs)) else None)
    .takeWhile(_.isDefined).map(_.get)
Odomontois
  • 15,918
  • 2
  • 36
  • 71