Generics Scala 2.8可从
根据我提出的另一个问题,我想进一步了解Scala方法Generics Scala 2.8可从,generics,scala,scala-2.8,Generics,Scala,Scala 2.8,根据我提出的另一个问题,我想进一步了解Scala方法TraversableLike[a].map,其签名如下: def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That > val s: Set[Int] = List("Paris", "London").map(_.length) s: Set[Int] Set(5,6) 请注意此方法的几点: 它使用一个函数将可遍历中的每个a转换为
TraversableLike[a].map
,其签名如下:
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That
> val s: Set[Int] = List("Paris", "London").map(_.length)
s: Set[Int] Set(5,6)
请注意此方法的几点:
- 它使用一个函数将可遍历中的每个
转换为aa
B
- 它返回
,并从[Repr,B,That]获取类型为That
CanBuildFrom的隐式参数
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That
> val s: Set[Int] = List("Paris", "London").map(_.length)
s: Set[Int] Set(5,6)
我不能完全理解的是编译器是如何强制执行与B
绑定的(也就是说,它是B的某个集合)。类型参数看起来独立于上面的签名和traitCanBuildFrom
本身的签名:
trait CanBuildFrom[-From, -Elem, +To]
Scala编译器如何确保
不能被强制进入没有意义的东西
> val s: Set[String] = List("Paris", "London").map(_.length) //will not compile
编译器如何确定调用范围内的隐式CanBuildFrom
对象是什么?请注意,map
的第二个参数是隐式参数。必须是具有适当类型的隐式in作用域,否则,您必须传递这样一个参数
在您的示例中,That
必须是Set[String]
,B必须是Int
,Repr
必须是List[String]
。因此,要进行编译,需要在作用域中使用以下隐式对象:
implicit object X: CanBuildFrom[List[String], Int, Set[String]]
范围内没有这样的东西。另外,breakOut
也不能提供它,因为它本身需要一个隐式的CanBuildFrom
,其第一个类型可以是任何类(一个Nothing
的反变体后代),但在其他方面受到其他类型的限制
例如,从列表的伴随对象查看的CanBuildFrom
工厂:
implicit def canBuildFrom [A] : CanBuildFrom[List, A, List[A]]
因为它通过A
绑定了第二个和第三个参数,所以所讨论的隐式方法不起作用
那么,对于这样的含蓄,人们如何知道去哪里寻找呢?首先,Scala确实将一些东西导入到所有作用域中。现在,我可以回忆起以下进口产品:
import scala.package._ // Package object
import scala.Predef._ // Object
// import scala.LowPriorityImplicits, class inherited by Predef
import scala.runtime._ // Package
由于我们关心隐式,请注意,当您从包导入内容时,唯一可能的隐式是单例。另一方面,从对象(单例)导入内容时,可以使用隐式定义、值和单例
现在,在Predef
和LowPriorityImplicits
中有CanBuildFrom
implicits,它们与字符串有关。它们使我们能够编写“这是一个字符串”映射(u.toInt)
那么,除了这些自动导入和您进行的显式导入之外,还有什么地方可以找到隐式导入呢?一个位置:应用方法的实例的伴随对象
我用复数形式说伴随对象,因为所讨论的实例类继承的所有特征和类的伴随对象可能包含相关的隐式。我不确定实例本身是否包含隐式的。老实说,我现在不能复制这个,所以我在这里肯定犯了某种错误
无论如何,请查看相关对象。Daniel-我如何知道在我的代码中的给定点范围内的隐式对象是什么?我意识到这就是问题的症结所在。具体在哪里?此外,这个问题与breakOut
无关。除了对象scala.Predef中的隐式转换外,您必须在相同或封闭范围中定义隐式,或者必须显式导入该隐式。“从包导入内容时,唯一可能的隐式是单例”Scala 2.8包对象仍然是这样吗?它们也可以包含隐式DEF和VAL。@JPP包对象既不是包也不是对象——它们是包对象。对象规则适用于它们。我的意思是,如果您编写了import scala.\u
,您将导入在包scala
中定义的所有类和特征,以及scala
包对象中的所有内容,其中可能包含隐式VAL和DEF(或者我弄错了?)。当然,scala包是预先导入的,这只是一个例子。这篇文章对记录做了很好的解释,这种用法有一个概念性的名称:返回类型多态性。
object ArrayBuffer extends SeqFactory[ArrayBuffer] {
/** $genericCanBuildFromInfo */
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, ArrayBuffer[A]] = new GenericCanBuildFrom[A]
def newBuilder[A]: Builder[A, ArrayBuffer[A]] = new ArrayBuffer[A]
}