繁体   English   中英

Scala模式匹配相当印刷

[英]Scala Pattern Matching pretty printed

是否有可能以某种方式将PartialFunction (让我们假设它总是只包含一个案例)编组成人类可读的东西?

假设我们有类型Any(messages:List [Any])的集合和使用模式匹配块定义的PartialFuntion [Any,T]的数量。

case object R1
case object R2
case object R3

val pm1: PartialFunction[Any, Any] = {
  case "foo" => R1
}

val pm2: PartialFunction[Any, Any] = {
  case x: Int if x > 10 => R2
}

val pm3: PartialFunction[Any, Any] = {
  case x: Boolean => R3
}

val messages: List[Any] = List("foo", 20)
val functions = List(pm1, pm2)

然后我们可以找到所提供的PF和相关应用程序匹配的所有消息

val found: List[Option[Any]] = functions map { f =>
  messages.find(f.isDefined).map(f)
}

但是如果我需要在人类可读的形式(用于记录)中得到“我所期望的”到“我所拥有的”的地图。 说,

(case "foo")         -> Some(R1)
(case Int if _ > 10) -> Some(R2)
(case Boolean)       -> None

那可能吗? 一些宏/元作品?

在运行时没有什么能很好地打印编译代码。

你可以编写一个宏来打印树的源代码并使用它吗? 大多数宏教程都以用于打印源代码的宏开头 - 参见http://www.warski.org/blog/2012/12/starting-with-scala-macros-a-short-tutorial/

也许:

// Given a partial function "pf", return the source code for pf
// as a string as well as the compiled, runnable function itself
def functionAndSource(pf: PartialFunction[Any, Any]): (String, PartialFunction[Any, Any]) = macro functionAndSourceImpl

def functionAndSourceImpl ...

val pm1: (String, PartialFunction[Any, Any]) = functionAndSource {
  case "foo" => R1
}

这在Scala中永远不会那么简单或好看。 Scala不是Lisp或Ruby:它是一种编译语言,并没有针对代码本身的反射进行优化。

谢谢你的回答。 使用Macro是一个有趣的选择。 但作为一种选择,解决方案可能是使用某种命名的部分函数。 这个想法是命名函数,所以在输出中你可以看到函数的名称而不是源代码。

object PartialFunctions {

  type FN[Result] = PartialFunction[Any, Result]

  case class NamedPartialFunction[A,B](name: String)(pf: PartialFunction[A, B]) extends PartialFunction[A,B] {
    override def isDefinedAt(x: A): Boolean = pf.isDefinedAt(x)
    override def apply(x: A): B = pf.apply(x)
    override def toString(): String = s"matching($name)"
  }

  implicit class Named(val name: String) extends AnyVal {
    def %[A,B](pf: PartialFunction[A,B]) = new NamedPartialFunction[A, B](name)(pf)
  }

}

那么你可以按如下方式使用它

import PartialFunctions._

val pm1: PartialFunction[Any, Any] = "\"foo\"" % {
  case "foo" => R1
}

val pm2: PartialFunction[Any, Any] = "_: Int > 10" % {
  case x: Int if x > 10 => R2
}

val pm3: PartialFunction[Any, Any] = "_: Boolean" % {
  case x: Boolean => R3
}

val messages: List[Any] = List("foo", 20)
val functions = List(pm1, pm2)

val found: List[Option[(String, Any)]] = functions map { case f: NamedPartialFunction =>
  messages.find(f.isDefined).map(m => (f.name, f(m))
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM