Scala奇怪的地图功能行为

时间:2013-03-15 13:20:35

标签: scala

为什么以下代码有效?

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中所指定的)。有人可以解释,请问这是怎么回事?

3 个答案:

答案 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)