表达式 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] 的东西,所以随后的调用@ 987654342@也可以。
另一种方法是
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 等库提供的类似功能,但这可能并不总是可取的,并且可能有点超出了这个问题的范围。