【发布时间】:2016-06-18 00:51:23
【问题描述】:
我不喜欢提取器的一件事是它们不能有参数。所以我不能有像Param 这样的提取器:
req match { case Param("foo")(foo) => … }
动态提取器?
这很不幸,我希望它有一天会改变,但今天早上我想我可以通过使用 Dynamic trait 来解决它。
object Params extends Dynamic {
def selectDynamic(name: String) = new {
def unapply(params: Map[String, String]): Option[String] = params.get(name)
}
}
...希望这能让我在这样的模式匹配语句中使用 Params:
req match { case Params.Foo(value) =>
// matching Map("Foo" -> "Bar"), extracting "Bar" in value
它不起作用
……但它不起作用。编译器似乎仍然感到困惑。
scala> Map("Foo" -> "bar") match { case Params.Foo(value) => value }
<console>:10: error: value applyDynamic is not a member of object Params
error after rewriting to Params.<applyDynamic: error>("Foo")
possible cause: maybe a wrong Dynamic method signature?
Map("Foo" -> "bar") match { case Params.Foo(value) => value }
^
<console>:10: error: not found: value value
Map("Foo" -> "bar") match { case Params.Foo(value) => value }
^
这让我感到惊讶,因为
object Params {
object Foo {
def unapply{params: Map[String, String]): Option[String] = …
}
}
可以正常工作。另外,如果我先将Params.Foo 分配给一个变量,一切都会好起来的:
scala> val Foo = Params.Foo
Foo: AnyRef{def unapply(params: Map[String,String]): Option[String]} = Params$$anon$1@f2106d8
scala> Map("Foo" -> "bar") match { case Foo(value) => value }
warning: there were 1 feature warning(s); re-run with -feature for details
res2: String = bar
这应该被认为是一个错误吗?
【问题讨论】:
-
当我尝试用你的
object Params extends Dynamic编译Map("" -> "") match { case Params.Foo(value) => 5 }时,编译器会因为NullPointerException而崩溃——对我来说绝对是个错误。 -
@wingedsubmariner 从我的 Scala REPL 的输出中可以看出,这不是我的方式
NullpointerException。 -
我不会在这里尝试与语言语法作斗争,而是简单地将提取器分配给一个常量并在
match块中使用该常量;在这里诉诸 Dynamic 看起来是个坏主意,在我看来,这会导致无法读取的非 Scalaesque 代码,而Dynamic并不适用。 -
@ErikAllik 我一直在使用像
Params.Foo这样的提取器作为嵌套对象。我看不出这是“不可读”和“非Scalaesque”的。 Unfiltered 一直使用它,也用于extracting parameters,所以我不明白为什么你不应该尝试让语法不那么冗长和笨拙。此外,ScalaDocs 没有提及Dynamic的用途,除了一个非常通用的描述,完全符合我的用例。 -
同意。最终的解决方案是参数化提取器,根据this,它应该在 Scala 2.11 中,但我还没有在发行说明中找到任何参考。
标签: scala