在scala中,在toMap之后添加不相关的行时编译错误消失了

时间:2012-10-28 21:45:22

标签: scala

这是在课程功能编程课程中交叉发布的,因为该论坛的活动少得多。

我写了下面的代码(部分被编辑,因为它是作业):

type Occurrences = List[(Char, Int)]
def subtract(x: Occurrences, y: Occurrences): Occurrences = {
  val mx: Map[Char, Int] = x toMap
  y.foldLeft (redacted) (redacted => simple expression using updated and -)) toList
}

这会产生以下编译错误:

type mismatch; found : Map[Char,Int] required: <:<[(Char, Int), (?, ?)]

但是,如果我通过val语句添加第三​​行的副本(没有toList),则错误就会消失:

type Occurrences = List[(Char, Int)]
def subtract(x: Occurrences, y: Occurrences): Occurrences = {
  val mx: Map[Char, Int] = x toMap
  val foo: Map[Char, Int] = y.foldLeft (redacted) (redacted => simple expression using updated and -))
  y.foldLeft (redacted) (redacted => simple expression using updated and -)) toList
}

我猜这与给类型检查器提供某种额外提示有关,但有没有人知道为什么会发生这种情况?

2 个答案:

答案 0 :(得分:3)

下面是一些例子和一些解释为什么会发生。

首先,工作和非工作案例:

scala> { List('a -> 1, 'b -> 2).toMap
     | println("aaa") }
aaa

scala> { List('a -> 1, 'b -> 2) toMap
     | println("aaa") }
<console>:9: error: type mismatch;
 found   : Unit
 required: <:<[(Symbol, Int),(?, ?)]
              println("aaa") }
                     ^

这是因为语法“obj method arg”被认为是“obj.method(arg)”,因此是“obj method \ n arg”,这样参数可以写在下一行。请注意以下内容:

scala> { val x = List('a -> 1, 'b -> 2) map 
     | identity
     | 
     | println(x) }
List(('a,1), ('b,2))

List('a -> 1, 'b -> 2).map(identity)相同。

现在发现奇怪的错误消息found : Unit, required: <:<[(Symbol, Int),(?, ?)]。碰巧toMap实际上需要一个参数,这是它的签名:

def toMap[T, U](implicit ev: <:<[A,(T, U)]): Map[T,U]

但它是一个隐式参数,因此在这种情况下不需要明确提供。但是当你使用obj method \n arg语法时,它会填充方法参数。在上面的非工作示例中,参数是println,其类型为Unit,因此编译器不接受它。

一种解决方法是让两个\n分隔这些行:

scala> { List('a -> 1, 'b -> 2) toMap
     | 
     | println("aaa") }
aaa

您还可以使用;分隔线条。

答案 1 :(得分:2)

@RexKerr&amp; @DidierDupont是对的,你遇到了问题,因为你像二进制运算符一样调用toMap,所以编译器吓坏了。

我的两分钱:您应该阅读Suffix Notation section of the Scala Style Guide