我最近开始使用scala,但我无法做出任何错误消息。对于以下代码,我得到了声明的消息(使用eclipse):
def helper: Int => List[Int] = x => x match {
case 2 => 2::1
...
}
我可以使用List(2,1)修复它,但是它与2 :: 1是一样的吗? 我有类似的问题,List(...)方法会更难使用,所以我真的想知道我的思维错误在哪里。
答案 0 :(得分:11)
中缀运算符被解释为Scala中的方法调用。如果中缀运算符以冒号结束,则它是对右操作数的方法调用,左操作数作为其参数。否则,它是对左操作数的方法调用,右操作数作为其参数。
换句话说,如果您执行x + y
,则它与x.+(y)
相同,即您在对象+
上调用方法x
,y
1}}作为参数。如果你x :: y
y.::(x)
与::
相同,则在对象y
上调用方法::
。
因此,在您的示例中,您在对象1
上调用方法Int
,这是一个Int
。但是,类::
没有::
方法,因此这不起作用,并且您收到一条错误消息,告诉您Int
方法不存在::
类。
要使::
正常工作,右侧操作数必须是一个列表(或其他具有2 :: 1 :: Nil
方法的内容),因此List()
可以正常工作。但是在这种情况下使用{{1}}似乎是更清洁的选择。
答案 1 :(得分:3)
表达式2::1
在Scala中被解释为:
{ val x = 2; 1.::(x) }
因为以冒号:
结尾的运算符是右关联的,如果op
是右关联的,则e1 op e2
被解释为{ val x = e1; e2.op(x) }
(请参阅Scala Language Reference, Section 6.12.3, p. 84, which is p. 92 of the PDF })。
出于此目的,基本上以下简化版本称为
1.::(2)
但是,1
的类型为Int
而Int
没有名称为::
的方法(并且也没有隐式转换为具有此类型的另一种类型方法),因此错误。
正如ayvango上面指出的那样,你可以使用
2::1::Nil
被解释为
Nil.::(2).::(1)
现在这非常有效,因为Nil
的类型为List[Nothing]
并且方法有::
,请参阅scala.collection.immutable.List此外,::
会返回键入List[Int]
,以便后续调用.::(1)
也可以。
另一种方式是
2::List(1)
变为List(1).::(2)
并且与上述原因相同。
您的混淆可能是因为您认为List(2,1)
与2::1
相同,但实际上是2::1::Nil
。将列表视为按归纳方式构建如下:
Nil
是一个列表head
是一个元素且tail
是一个列表,那么head::tail
就是一个列表如列表的实施(简化版,省略特征)所见证的
sealed abstract class List[+A]
final case class ::[B](head: B, tl: List[B]) extends List[B]
object Nil extends List[Nothing]
因此,列表始终以Nil
演示形式“以”::
结尾。
在旁注中,您还可以尝试使用
之类的内容自动将Int
包裹到List[Int]
中
implicit def wrap(x : Int) : List[Int] = List(x)
或使用Scalaz等库提供的类似功能,但这可能并不总是可取的,可能有点超出了这个问题的范围。
答案 2 :(得分:2)
::是List上定义的方法。您正尝试将此运算符与Int类型一起使用。 看看:http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.List
正如@ayvango指出的那样,你可以这样做:
def helper: Int => List[Int] = x => x match {
case 2 => 2 :: 1 :: Nil
}
答案 3 :(得分:0)