如何将 `String` 改造成 `Iterable[E]`
How to pimp `String` as `Iterable[E]`
我正在使用 Scala 的 implicit class
机制,但无法将 java.lang.String
识别为 Iterable[A]
。
implicit class PStream[E](stream: Iterable[E]) {
def splitOn(test: Iterable[E] => Boolean): Option[(Iterable[E], Iterable[E])] = {
???
}
}
根据上述定义,IntelliJ 和 SBT 声明...
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))
...当我尝试这个...
line: String =>
val Some((identifier: String, patternn: String)) =
line
// take the identifier
.splitOn(s => Character.isWhitespace(s.head))
那是因为 Iterable[E]
是 Scala 的一个特性,因此是一个相对 "recent" 的发明,而 java.lang.String
是一个基本的 Java 数据类型,自版本以来一直存在1.0。从 1995 年开始。显然,java.lang.String
没有实现 Iterable[E]
。
此外,即使存在从 String
到 Iterable[E]
的隐式转换,Scala 也不会 永远不会 尝试对单个表达式进行多次隐式转换.
如果你想拉皮条 String
,你必须将 String
作为一个参数传递给你的隐式 class。编译器将拒绝构建多个隐式转换的疯狂塔,否则会使编译时间无法接受。
你可以尝试的是这样的:
implicit def toPStreamOps[X, E](x: X)(implicit iter: IsIterable[X, E])
: PStream[X, E] = ???
然后提供单独的
implicit object StringIsIterableChar
extends IsIterable[String, Char] {
def asIterable(s: String): Iterable[Char] = ???
}
这将为您提供几乎相同的功能,但不需要不受控制的隐式转换爆炸。
String
(还有 Array[T]
)继承自 Java,因此不扩展 Scala 的 Iterable
。但是在 Scala 中,有 String
和 Array[T]
的隐式包装到扩展 IndexedSeq
的对象中,因此 Iterable
.
请求参数隐式转换的原始接口是 view bound:
implicit class PStream[E, T <% Iterable[E]](stream: T) {
/* ... */
}
现在已弃用,但您可以将隐式转换请求为隐式参数:
implicit class PStream[E, T](stream: T)(implicit toIterable: T => Iterable[E]) {
/* ... */
}
此代码将支持正常的 Iterable
s,以及 String
s 和 Array
s。
我正在使用 Scala 的 implicit class
机制,但无法将 java.lang.String
识别为 Iterable[A]
。
implicit class PStream[E](stream: Iterable[E]) {
def splitOn(test: Iterable[E] => Boolean): Option[(Iterable[E], Iterable[E])] = {
???
}
}
根据上述定义,IntelliJ 和 SBT 声明...
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))
...当我尝试这个...
line: String =>
val Some((identifier: String, patternn: String)) =
line
// take the identifier
.splitOn(s => Character.isWhitespace(s.head))
那是因为 Iterable[E]
是 Scala 的一个特性,因此是一个相对 "recent" 的发明,而 java.lang.String
是一个基本的 Java 数据类型,自版本以来一直存在1.0。从 1995 年开始。显然,java.lang.String
没有实现 Iterable[E]
。
此外,即使存在从 String
到 Iterable[E]
的隐式转换,Scala 也不会 永远不会 尝试对单个表达式进行多次隐式转换.
如果你想拉皮条 String
,你必须将 String
作为一个参数传递给你的隐式 class。编译器将拒绝构建多个隐式转换的疯狂塔,否则会使编译时间无法接受。
你可以尝试的是这样的:
implicit def toPStreamOps[X, E](x: X)(implicit iter: IsIterable[X, E])
: PStream[X, E] = ???
然后提供单独的
implicit object StringIsIterableChar
extends IsIterable[String, Char] {
def asIterable(s: String): Iterable[Char] = ???
}
这将为您提供几乎相同的功能,但不需要不受控制的隐式转换爆炸。
String
(还有 Array[T]
)继承自 Java,因此不扩展 Scala 的 Iterable
。但是在 Scala 中,有 String
和 Array[T]
的隐式包装到扩展 IndexedSeq
的对象中,因此 Iterable
.
请求参数隐式转换的原始接口是 view bound:
implicit class PStream[E, T <% Iterable[E]](stream: T) {
/* ... */
}
现在已弃用,但您可以将隐式转换请求为隐式参数:
implicit class PStream[E, T](stream: T)(implicit toIterable: T => Iterable[E]) {
/* ... */
}
此代码将支持正常的 Iterable
s,以及 String
s 和 Array
s。