I am working with Scala's implicit class
mechanism and can't get java.lang.String
recognized as Iterable[A]
.
implicit class PStream[E](stream: Iterable[E]) {
def splitOn(test: Iterable[E] => Boolean): Option[(Iterable[E], Iterable[E])] = {
???
}
}
With just the above definition, IntelliJ and SBT state that ...
Error:(31, 8) value splitOn is not a member of String possible cause: maybe a semicolon is missing before `value splitOn'? .splitOn(s => Character.isWhitespace(s.head))
... when I try this ...
line: String =>
val Some((identifier: String, patternn: String)) =
line
// take the identifier
.splitOn(s => Character.isWhitespace(s.head))
That's because Iterable[E]
is a Scala trait, and as such a relatively "recent" invention, whereas java.lang.String
is a fundamental Java datatype that has been there since version 1.0. from 1995. Obviously, java.lang.String
does not implement Iterable[E]
.
Moreover, even if there is an implicit conversion from String
to Iterable[E]
, Scala will never attempt more than one implicit conversion on a single expression.
If you want to pimp String
, you have to pass String
as a single parameter to your implicit class. The compiler will refuse to build crazy towers of multiple implicit conversions, because it would make the compilation time inacceptable otherwise.
What you could try instead would be something like this:
implicit def toPStreamOps[X, E](x: X)(implicit iter: IsIterable[X, E])
: PStream[X, E] = ???
and then provide a separate
implicit object StringIsIterableChar
extends IsIterable[String, Char] {
def asIterable(s: String): Iterable[Char] = ???
}
This would give you pretty much the same functionality, but it would not require an uncontrolled explosion of implicit conversions.