通过apply
方法访问Scala中的集合元素。话虽如此,我试图从标准输入读取数字,并在第一行中将第二个作为int。
def main(args: Array[String]): Unit = {
val number = StdIn.readLine().split(" ").map(_.toInt)(1)
}
IntelliJ标记此1
并显示错误(编译尝试后显示错误):
错误:(11,60)类型不匹配;发现:Int(1)要求: scala.collection.generic.CanBuildFrom [数组[字符串],诠释,?] val number = StdIn.readLine()。split(“”)。map(_。toInt)(1)
折叠括号中的表达式也没有帮助。但是,当我将映射输入拆分为int数组并将元素转换为其他行时,一切正常。
def main(args: Array[String]): Unit = {
val numbers = StdIn.readLine().split(" ").map(_.toInt)
numbers(1)
}
显式调用apply
也可以完成工作:
val number = StdIn.readLine().split(" ").map(_.toInt).apply(1)
为什么会发生这种奇怪的行为?通过array(5)
获取元素只是array.apply(5)
的快捷方式,不是吗?
答案 0 :(得分:2)
正如编译器已经指出的那样,map
定义了两个arg列表。第二个包含一个隐式参数:implicit bf: CanBuildFrom[Repr, B, That]
对于绝大多数情况,用户不必担心指定第二个arg。具体来说,在您的情况下,这就是编译器"指出":
StdIn.readLine().split(" ").map(_.toInt)(Array.canBuildFrom[Int])
因此,如果不需要写出apply
,则以下是唯一的选择:
StdIn.readLine().split(" ").map(_.toInt)(Array.canBuildFrom[Int])(1)
有点反直觉的是,添加一组括号仍然不能解决问题:
( StdIn.readLine().split(" ").map(_.toInt) )(1) //does not compile, same error
也许最好通过一个更简单的例子来展示自己的目标。考虑以下功能:
def add(x:Int)(y:Int) = x + y
add(2)
的类型为Int => Int
(因为我们尚未指定y
)。请注意,在其周围添加一组括号并不会更改返回类型,即(add(2))
仍然具有类型Int => Int
。同样,在(Array("1").map(_.toInt))(1)
使用速记之前,CanBuildFrom
仍然需要apply
的实例。
有关Scala集合的建议阅读:
和隐式范围:
答案 1 :(得分:1)
您与map
的隐含参数发生冲突。这是需要明确调用apply的情况之一。
这是一些复制错误的REPL:
scala> class Foo {
def apply() { println("bar") }
}
scala> def makeFoo(): Foo = new Foo
scala> makeFoo()()
bar // got the println from the apply here
scala> def makeFooImplicit()(implicit x: Int): Foo = new Foo
scala> implicit val x = 5
scala> makeFooImplicit()()
<console>:11: error: not enough arguments for method makeFooImplicit:(implicit x: Int)Foo.
Unspecified value parameter x.
makeFooImplicit()()