【发布时间】:2020-02-13 04:18:45
【问题描述】:
我想通过列表使用match case 语句。这是我的用例:
val test: String = "test3"
val option: String = getMyOption(test) match {
case Some(o: String) => o
case None => ""
}
test match {
case `test1` | `test2` => doSomething(test, option, param1)
case `test3` | `test4` | `test5` => doSomethingElse(test, param1, param2)
case `test6` => doMyJob()
case `test7` => doMyJob(param2, param3)
case other =>
throw getUnsupportedTestOperation(other)
}
我尝试了以下方法,但似乎在匹配之前对函数进行了评估,因为我从 doSomething(test, option) 函数中获得了 NullPointerException(在 test3 案例中不应该调用它)。
def matchList[T](string: String, cases: => Map[Array[String], T], exception: => Exception): T = {
val matched: Option[T] = cases collectFirst {
case (list, matching) if list.contains(string) => matching
}
if(matched.isDefined) matched.get else throw exception
}
val mapping1: Array[String] = Array("test1", "test2")
val mapping2: Array[String] = Array("test3", "test4", "test5")
val mapping3: Array[String] = Array("test6")
val mapping4: Array[String] = Array("test7")
val option: String = getMyOption(test).getOrElse("undefined")
val testMapping: Map[Array[String], Unit] = Map(
mapping1 -> doSomething(test, option, param1),
mapping2 -> doSomethingElse(test, param1, param2),
mapping3 -> doMyJob(),
mapping4 -> doMyJob(param2, param3)
)
matchList(test, testMapping, getUnsupportedTestOperation(other))
在这种情况下,我传递 Unit 之类的回调函数,但我也想使用其他类型(例如:String、Array[String]..)。我想念什么?如何避免在匹配之前评估 Map 内容?是否可以在match case 语句中使用列表?还是有更简单的方法来实现这一目标? (我想避免在match case 中包含if 语句。)
编辑
我的结局
def matchList[T](matchCase: String, matchClause: => ListMap[List[String], T], exception: => Exception): T = {
val matched: Option[T] = matchClause.find(_._1.contains(matchCase)).map { case (_, output) => output }
if(matched.isDefined) matched.get else throw exception
}
用法
def testMatchList(input: String, option: String, exception: Exception): Unit = {
val testMapping: ListMap[List[String], () => Unit] = ListMap(
mapping1 -> match1(input),
mapping2 -> match2(input, option),
mapping3 -> match3(),
mapping4 -> match4(option)
) // where matching cases signatures looks like => def match1(...): () => Unit = () => ...
val method = scalaHelper.matchList(input, testMapping, exception)
method()
}
注意:我还不知道如何从 testMatchList 定义中提取 testMapping...
【问题讨论】:
-
使用
.get,.orNull充其量不是惯用的,可能是代码异味
标签: scala generics callback pattern-matching