【问题标题】:Problem rewriting scala method post upgrade to scala 2.12 (from 2.11)升级到 scala 2.12(从 2.11)后重写 scala 方法的问题
【发布时间】:2021-10-22 03:42:49
【问题描述】:

我的项目中有以下小而复杂的方法:

private def indent ( s : String )
  = s.lines.toStream match {
    case h +: t =>
      ( ("- " + h) +: t.map{"| " + _} ) mkString "\n"
    case _ => "- "
  }

在将我的项目从 Scala 2.11 升级到 2.12 后,它将不再编译。错误:

CaseClassString.scala:14: value toStream is not a member of java.util.stream.Stream[String]

我试过这样重写:

private def indent ( s : String )
  = Stream(s.lines) match {
    case h +: t =>
      ( ("- " + h) +: t.map{"| " + _} ) mkString "\n"
    case _ => "- "
  }

但它不起作用。

此方法在以下项目中找到: https://github.com/nikita-volkov/sext

该函数将转换如下字符串:

metricResult: column: value: city
function: density
value: metricValue: 0.1

到:

- metricResult: column: value: city
| - function: density
| - value: metricValue: 0.1

有人对如何为 Scala 2.12 重写此方法有其他想法吗?

【问题讨论】:

  • 该方法应该做什么?自 Scala 2.11 以来,发生了很多变化(特别是在 Java 方面),您可以只查看更新的文档,而不是随意尝试。您当前的 Java 版本是什么?
  • 更新了问题,详细说明了它的作用。我正在使用 Java 1.8
  • 第 3 列和第 4 列中嵌套的 - s 应该来自哪里?当应用于"foo\nbar\nbaz" 时,它会产生"- foo\n| bar\n| baz",而不是"-foo\n| - bar\n| - baz"
  • 此错误表明您正在使用 Java 11 或更高版本 :: CaseClassString.scala:14: value toStream is not a member of java.util.stream.Stream[String]
  • 那么对我来说是个谜。我的 IntelliJ 项目使用的是 Java 8。我什至没有安装 11。

标签: string scala scala-2.12


【解决方案1】:

我怀疑您还将 JVM 从 Java 8 升级到 Java 11(或者正在使用编写的代码在 Java 11 上的 Java 8 上运行)。 Java 11 向String 添加了一个lines 方法,这导致java.util.Stream[String]。在 Java 8 上,String 没有 lines 方法,这意味着 Scala 编译器可以将 String 隐式转换为 scala.collection.immutable.StringOpslines 方法的结果类型为 Iterator[String]

这里的诀窍是明确表示你想使用StringOps.lines 而不是String.lines,所以像

val lines = (s: scala.collection.immutable.StringOps).lines
lines.toStream match {
  // etc.
}

【讨论】:

  • 请注意,也可以将 Java 流转换为 Scala 迭代器,但如果针对 Java 8 编译则会中断。
  • 感谢您的回答。 @sarveshseri 有同样的想法。我实际上并没有更改为 Java 11,但这也在待办事项列表中。
【解决方案2】:

看来您不仅升级了 Scala,还升级了 Java 版本。如果您只是查看与 Java 和 Scala 的 String 相关的更改,则该错误很容易理解。

import scala.collection.immutable.StringOps

def indent(s : String): String =
  (s: StringOps).lines.toStream match {
    case h +: t =>
      ( ("- " + h) +: t.map{"| " + _} ) mkString "\n"
    case _ => "- "
  }

或者,如果您正在使用 Java 11 并且不需要 Stream,那么,

def indent(s : String): String =
  s.lines.toArray.toList match {
  case h :: t =>
    val indented = ("- " + h) :: t.map{"| " + _}
    indented.mkString("\n")
  case _ => "- "
}

【讨论】:

    【解决方案3】:

    与安德烈的解决方案非常相似,但有效:

    def indent(s: String) = s.linesIterator.mkString("- ", "\n| - ", "")
    

    代码在scatie 运行。

    【讨论】:

      猜你喜欢
      • 2017-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-02
      • 2019-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多