【问题标题】:Scala 2.12 tells me Stack is deprecated, how to replace it exactly (and why I don't see the proper warning in IntelliJ)Scala 2.12 告诉我 Stack 已被弃用,如何准确替换它(以及为什么我在 IntelliJ 中看不到正确的警告)
【发布时间】:2017-10-07 14:03:42
【问题描述】:

我设置了一个 Scala 项目并从 http://www.scalatest.org/ 添加了这个 sn-p

import collection.mutable.Stack
import org.scalatest._

class ExampleSpec extends FlatSpec with Matchers {

  "A Stack" should "pop values in last-in-first-out order" in {
    val stack = new Stack[Int]
    stack.push(1)
    stack.push(2)
    stack.pop() should be (2)
    stack.pop() should be (1)
  }

  it should "throw NoSuchElementException if an empty stack is popped" in {
    val emptyStack = new Stack[Int]
    a [NoSuchElementException] should be thrownBy {
      emptyStack.pop()
    } 
  }
}

并且 IntelliJ (IDEA 2017.1.2) 向我显示使用 new Stack[Int] 的警告:

搜索警告向我显示了这个问题: https://issues.scala-lang.org/browse/SI-9068

但我仍然有这些问题:

  1. 我得到一个弹出窗口,它分为两个区域。这是否意味着有两个警告,每个警告有 2 行。什么是真实信息?对于第二个区域,我看到 必须添加前缀正在建设中

  2. 为什么我没有看到正确的弃用警告,就像在此处添加的一样:https://github.com/scala/scala/pull/5260/files#diff-1ab096eae7e5571b6410a123567aac0aR57

  3. 在 github/API 文档上他们说:Use a List assigned to a var instead 但我不能只用List 替换Stack,因为.push() 不适用于该类。还是我应该完全切换到 List API?使用varval 分配列表有什么区别? 例如,我不能通过list.add(2) 添加项目,即使它是用val 分配的吗?

我通过 Homebrew 安装了 Scala 2.12.2。我不确定我是否是 IntelliJ,它使用的是自己的版本,因为我也需要通过 IntelliJ 下载它,但无论如何它是相同的版本,所以我的设置如下所示:


顺便说一句:在终端 / Scala REPL 我得到这个输出

scala> val stack = new Stack[Int]
<console>:14: warning: class Stack in package mutable is deprecated (since 2.12.0): Stack is an inelegant and potentially poorly-performing wrapper around List. Use a List assigned to a var instead.
       val stack = new Stack[Int]
                       ^

因此,适当的弃用警告似乎在那里起作用。

【问题讨论】:

    标签: scala intellij-idea


    【解决方案1】:

    已弃用的消息

    一般来说,当存在不推荐使用的函数时,您只会看到您看到的一般响应。要获得详细消息,您应该使用 -deprecation 进行编译。要更改此使用设置-> 构建、执行、部署-> 编译器-> scala 编译器并检查相关选项(在您的情况下会出现弃用警告,但其余大部分可能是个好主意)

    引用必须加前缀警告

    这是一个完全不相关的警告。使用可变类时,scala 样式是使用 mutable 作为前缀。即使用这个:

    import collection.mutable    
    val a = new mutable.Stack[Int]
    

    而不是

    import collection.mutable.Stack    
    val a = new Stack[Int]
    

    这是因为 scala 中的默认思维方式通常应该是使用不可变集合,除非您有充分的理由不这样做。

    如果这让您感到困扰,您可以随时关闭此检查。

    用什么来代替堆栈

    堆栈被删除的原因是它只是一个列表的包装器。 Push 只是添加一个新的头部,而 pop 只是获取尾部。

    这意味着如果你有:

    val a = new mutable.Stack
    a.push(XXX)
    a.pop(XXX)
    

    您可以将其替换为:

    var a = new List
    a = XXX +: a
    a = a.tail
    

    请注意,一般情况下,您可以在此处使用不可变列表。

    编辑

    为了更容易理解,在 var a = new List 中创建的 List 应替换为实际选择的列表。

    标准方法是使用标准的 scala 创建方法,例如:

    var a = List[Int]()  
    var a: List[Int] = Nil 
    

    但如果需要更多功能,也可以根据需要选择另一个具体列表。

    【讨论】:

    • 更改编译器设置没有帮助,我仍然看到与此设置相同的消息:anonimag.es/image/JT9sfQ6
    • 能否请您粘贴完整的sn-p 如何替换我提供的文件。使用List 对我不起作用。我得到:类列表是抽象的,无法实例化
    • 我在答案中添加了关于列表创建选项的说明。至于 intellij 编译器选项,您是正确的,我建议的修复处理的是编译(构建)而不是检查。我不熟悉更改检查部分的方法
    • 最好使用前置操作,因为它需要 O(1),并通过“head”访问最后插入的元素,例如var a = List[Int](); a = 1 :: a; a.head
    • 正在寻找关于它被弃用的为什么的解释。得到明确的解决方案如何替换pushpop。很酷的答案。
    【解决方案2】:

    ListBuffer 是一个很好的替代品,因为它提供了恒定的时间前置和删除。 mutable.List 是另一种选择。详情请见https://stackoverflow.com/a/5753935/839733

    【讨论】:

      【解决方案3】:

      用 var 或 val 分配列表有什么区别? 例如,我不能通过 list.add(2) 添加项目,即使它已分配 用 val 吗?

      您可以将可变的 ListBuffer(它们不会创建可变列表)分配给 val,或者将常规的不可变列表分配给 var。这取决于您,但使用不可变数据结构更实用。这是我认为@abhijit-sarkar 正在解决的问题的一部分。

      import scala.collection.mutable
      
      object StackReplace{
        implicit class StackListBuffer[T](listBuffer:mutable.ListBuffer[T]){
          def push(t:T):Unit = listBuffer.prepend(t)
        }
        implicit class StackList[T](list:List[T]){
          def push(t:T):List[T] = t +: list
        }
      }
      import StackReplace._
      val a = mutable.ListBuffer(1,2,3)
      a.prepend(0)
      a           // ListBuffer(0, 1, 2, 3)
      
      var b = List(1,2,3)
      b = 0 +: b  // List(0, 1, 2, 3)
      
      a.push(-1)
      a           // ListBuffer(-1, 0, 1, 2, 3)
      b.push(-1)  // List(-1, 0, 1, 2, 3)
      

      实现 pop 留给读者作为练习。

      【讨论】:

        猜你喜欢
        • 2012-04-29
        • 2022-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-25
        • 1970-01-01
        • 2015-02-21
        • 2013-09-04
        相关资源
        最近更新 更多