为什么以下代码有效?
scala> List(1,2,3) map "somestring"
res0: List[Char] = List(o, m, e)
它适用于2.9和2.10。 展望着这一点:
[master●●] % scala -Xprint:typer -e 'List(1,2,3) map "somestring"' ~/home/folone/backend
[[syntax trees at end of typer]] // scalacmd2632231162205778968.scala
package <empty> {
object Main extends scala.AnyRef {
def <init>(): Main.type = {
Main.super.<init>();
()
};
def main(argv: Array[String]): Unit = {
val args: Array[String] = argv;
{
final class $anon extends scala.AnyRef {
def <init>(): anonymous class $anon = {
$anon.super.<init>();
()
};
immutable.this.List.apply[Int](1, 2, 3).map[Char, List[Char]](scala.this.Predef.wrapString("somestring"))(immutable.this.List.canBuildFrom[Char])
};
{
new $anon();
()
}
}
}
}
}
看起来它会转换为WrappedString
,它有一个apply方法。这解释了它是如何工作的,但没有解释,WrappedString
如何被接受到A => B
类型的参数中(如scaladoc中所指定的)。有人可以解释,请问这是怎么回事?
答案 0 :(得分:7)
collection.Seq[Char]
,PartialFunction[Int, Char]
的子类型,Int => Char
的子类型:
scala> implicitly[collection.immutable.WrappedString <:< (Int => Char)]
res0: <:<[scala.collection.immutable.WrappedString,Int => Char] = <function1>
因此,只有一个隐式转换发生 - 原始String => WrappedString
,因为我们将字符串视为函数,所以会启动它。
答案 1 :(得分:4)
因为WrappedString
具有超类型(Int) => Char
:
Scaladoc并展开“线性超类型”部分。
答案 2 :(得分:2)
其他人已经明确表示你的String实现了一个接受Int并返回一个char的函数(即Int =&gt; Char表示法)。这允许这样的代码:
scala> "Word".apply(3)
res3: Char = d
扩展您的示例会使其更清晰,可能:
List(1,2,3).map(index => "somestring".apply(index))
List(1,2,3).map(index => "somestring"(index)) //(shorter, Scala doesn't require the apply)
List(1,2,3).map("somestring"(_)) //(shorter, Scala doesn't require you to name the value passed in to map)
List(1,2,3).map("somestring") //(shorter, Scala doesn't require you to explicitly pass the argmument if you give it a single-arg function)