Reputation: 32284
I am trying to use the new Scala 2.10 implicit class
mechanism to convert a java.sql.ResultSet
to a scala.collection.immutable.Stream
. In Scala 2.9 I use the following code, which works:
/**
* Implicitly convert a ResultSet to a Stream[ResultSet]. The Stream can then be
* traversed using the usual methods map, filter, etc.
*
* @param resultSet the Result to convert
* @return a Stream wrapped around the ResultSet
*/
implicit def resultSet2Stream(resultSet: ResultSet): Stream[ResultSet] = {
if (resultSet.next) Stream.cons(resultSet, resultSet2Stream(resultSet))
else {
resultSet.close()
Stream.empty
}
}
I can then use it like this:
val resultSet = statement.executeQuery("SELECT * FROM foo")
resultSet.map {
row => /* ... */
}
The implicit class
that I came up with looks like this:
/**
* Implicitly convert a ResultSet to a Stream[ResultSet]. The Stream can then be
* traversed using the usual map, filter, etc.
*/
implicit class ResultSetStream(val row: ResultSet)
extends AnyVal {
def toStream: Stream[ResultSet] = {
if (row.next) Stream.cons(row, row.toStream)
else {
row.close()
Stream.empty
}
}
}
However, now I must call toStream
on the ResultSet
, which sort of defeats the "implicit" part:
val resultSet = statement.executeQuery("SELECT * FROM foo")
resultSet.toStream.map {
row => /* ... */
}
What am I doing wrong?
Should I still be using the implicit def
and import scala.language.implicitConversions
to avoid the "features" warning?
UPDATE
Here is an alternative solution that converts the ResultSet
into a scala.collection.Iterator
(only Scala 2.10+):
/*
* Treat a java.sql.ResultSet as an Iterator, allowing operations like filter,
* map, etc.
*
* Sample usage:
* val resultSet = statement.executeQuery("...")
* resultSet.map {
* resultSet =>
* // ...
* }
*/
implicit class ResultSetIterator(resultSet: ResultSet)
extends Iterator[ResultSet] {
def hasNext: Boolean = resultSet.next()
def next() = resultSet
}
Upvotes: 4
Views: 607
Reputation: 32719
I don't see a reason here to use implicit classes. Stick to you first version. Implicit classes are mainly useful (as in "concise") to add methods to existing types (the so called "enrich my library" pattern). It is just syntactic sugar for a wrapper class and an implicit conversion to this class.
But here you are just converting (implicitly) from one preexisting type to another preexisting type. There is no need to define a new class at all (let alone an implicit class).
In your case, you could make it work using implicit classes by making ResultSetStream
extend Stream
and implementing as a proxy to toStream
. But that would really a lot fo trouble for nothing.
Upvotes: 4