scala 使用com-lihaoyi.github.io/PPrint/打印case类的属性名称时遇到困难

rvpgvaaj  于 2023-08-05  发布在  Scala
关注(0)|答案(1)|浏览(113)

我真的很喜欢这个库对漂亮的打印case类示例的承诺!但是我希望我的输出包括我的case类的属性名,到目前为止我还不够。
以下是我最近的尝试:

import fansi.Str
 object Testo extends App {

case class Person(name: String, age: Int, address: Address)
case class Address(street: String, city: String)

val person = Person("John Doe", 30, Address("123 Main St", "New York"))
val list = List(person, person)
val map = Map("foo" -> list)
val map2 = Map("foo" -> list, "bar" -> person)

val pprint2 =
  pprint.copy(
    additionalHandlers = {
      case p: Product => {
        val stringo: Seq[String] = p.productIterator.toSeq.map {
              case (name, value) => s"$name = ${pprint.apply(value)}"
          }

        val result = p.productIterator.toSeq.map(item => "x")
        pprint.Tree.Literal(stringo.mkString(""))
      }
    }
  )

pprint2.pprintln(map2)
val result: Iterator[Str] = pprint2.tokenize(map2, showFieldNames = true)

val xx = result.map(_.toString()).mkString("")
System.out.println("xx:" + xx)

字符串
}
I get a crash崩溃like this->

Connected to the target VM, address: '127.0.0.1:63150', transport: 'socket'
Exception in thread "main" scala.MatchError: Person(John Doe,30,Address(123 Main St,New York)) (of class Person)
        at Testo$$anonfun$1.$anonfun$applyOrElse$1(Test.scala:32)
        at scala.collection.immutable.Stream.map(Stream.scala:418)
        at Testo$$anonfun$1.applyOrElse(Test.scala:32)
        at scala.PartialFunction$Lifted.apply(PartialFunction.scala:228)
        at scala.PartialFunction$Lifted.apply(PartialFunction.scala:224)
        at pprint.Walker.treeify(Walker.scala:50)
        at pprint.Walker.$anonfun$treeify$3(Walker.scala:78)
        at scala.collection.Iterator$$anon$11.nextCur(Iterator.scala:486)
        at scala.collection.Iterator$$anon$11.hasNext(Iterator.scala:492)
        at pprint.Renderer.rec(Renderer.scala:29)
        at pprint.PPrinter.tokenize(PPrinter.scala:165)
        at pprint.PPrinter.pprintln(PPrinter.scala:141)
        at Testo$.delayedEndpoint$Testo$1(Test.scala:42)
        at Testo$delayedInit$body.apply(Test.scala:15)
        at scala.Function0.apply$mcV$sp(Function0.scala:39)
        at scala.Function0.apply$mcV$sp$(Function0.scala:39)
        at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:17)
        at scala.App.$anonfun$main$1$adapted(App.scala:80)
        at scala.collection.immutable.List.foreach(List.scala:431)
        at scala.App.main(App.scala:80)


任何关于如何做到这一点的想法,最欢迎!

zkure5ic

zkure5ic1#

问题与库无关。你的代码抛出了MatchError
这个类实现了当一个对象与模式匹配表达式的任何模式都不匹配时抛出的错误。
这是说,没有一个案例与你是pattern matching的对象相匹配。
排队

val stringo: Seq[String] = p
  .productIterator // returns a Iterator[Any]
  .toSeq // converts Iterator[Any] to Seq[Any]
  .map {
    case (name, value) => // Any doesn't match with Tuple2(x, y)
      s"$name = ${pprint.apply(value)}"
  }

字符串
正如我在注解中详细说明的,Product.productIterator返回一个Iterator[Any]类型的值。当你写一个像

case (x, y) => //...


它需要一个包含两个元素的元组。我猜你想得到元素的名字和值。在这种情况下,您可以将方法Product.productElementNames与productIterator结合使用。

case p: Product => {
  val nameAndValue = p.productElementNames.zip(p.productIterator)
  val stringo: Seq[String] = nameAndValue.toSeq.map {
    case (name, value) => s"$name = ${pprint.apply(value)}"
  }
  pprint.Tree.Literal(stringo.mkString(", "))
}


我认为那样做会产生预期的产出

相关问题