Scala中的不可变列表

Cod*_*er0 1 scala list add immutability

我只想弄清楚像List这样的不可变的东西是如何工作的,以及我如何为它添加东西?

我很抱歉问这些愚蠢的问题,但是为什么我的列表在打印时总是空的?

var end = false
val list = List()
while (!end) {
  val input = scala.io.StdIn.readLine("input:")
  if (input == "stop" ) end = true
  else input :: list
}

println(list)

}
Run Code Online (Sandbox Code Playgroud)

很抱歉给我带来不便和这个相当愚蠢的问题!

Jör*_*tag 6

我只想弄清楚像List这样的不可变的东西是如何工作的,以及我如何为它添加东西?

你不能.毕竟,这就是不可改变的意思.如果拉丁美洲是不是你的那杯茶,英译不变的不可改变的.现在应该清楚,为什么你不能改变不可改变的东西.

我很抱歉问这些愚蠢的问题,但是为什么我的列表在打印时总是空的?

您创建一个空列表,并且永远不会更改它(因为它无论如何都无法更改).所以,当然它是空的.

但是,你可以做的是创建一个列表,它几乎与列表完全相同,只是在前面添加了一个新项目.这就是你在这里做的事情:

input :: list
Run Code Online (Sandbox Code Playgroud)

但是,您不会将此新列表分配到任何位置,也不会将其返回,您完全忽略它.

如果你想以任何方式实际使用你的列表,你需要以某种方式记住它.最明显的解决方案是将其分配给变量:

var end = false
var list: List[String] = List() // note: `var` instead of `val`
while (!end) {
  val input = scala.io.StdIn.readLine("input:")
  if (input == "stop" ) end = true
  else list = input :: list // note: assign to `list`
}
println(list)
Run Code Online (Sandbox Code Playgroud)

然而,这不是非常惯用的.毕竟,我们现在已经采用了一个不可变的列表并将其分配给一个可变变量......我们刚刚提出了可变性.

相反,我们可以使用递归解决方案:

def buildListFromInput(list: List[String] = List()): List[String] = {
  val input = scala.io.StdIn.readLine("input:")
  if (input == "stop") list else buildListFromInput(input :: list)
}

println(buildListFromInput())
Run Code Online (Sandbox Code Playgroud)

这个解决方案不仅是递归的,递归调用也处于尾部位置(IOW,该方法是尾递归的),这意味着它将像while循环一样高效(事实上​​,它将被编译成while循环,或者更准确地说,进入a GOTO).Scala语言规范保证Scala的所有实现都必须消除直接尾递归.