1

使用Scala,有没有什么方法可以动态地构建一个模式匹配的列表模式?Scala模式匹配的动态稳定标识符

例如,假设我使用稳定标识符解析字符串列表,像这样:

def matchingAndDispatch(xs: List[String])= { 
    case `namespace` :: value :: `elementTerminator` :: rest => { 
    // Do Something... 
    } 
    case `openBracket` :: rest => { 
    // Do Something Else... 
    } 
    case `closeBracket` :: `elementTerminator` :: rest => { 
    // Or perhaps something else... 
    } 
} 

现在,假设有将是一个很大的情况下条款和我的希望能够将它们存储在某种可以在运行时更改的集合中 - 不一定是模式本身,但可以更改模式集合。我做了虚构类MatchClause在下面的代码解释或多或少是我心目中 - 基本上遍历模式的集合(即匹配条款),并在同一时间匹配一个:

def matchingAndDispatch(xs: List[String], matchingClauses:List[MatchClause])= { 
    if(!matchingClauses.empty){ 
    case matchingClauses.head => { 
    // Do Something... 
    } 
    case _ => matchingAndDispatch(xs, matchingClause.tail) 
    } 
    }else throw new Error("no match") 

是Scala API中有什么可以达到这个目的?我没有找到任何东西。或者,也许我正在以这种错误的方式去做?

+0

从它的外观来看,你可能会使用Parser Combinators。只需定义上下文无关语法,Scala将为您完成剩下的工作。你实际上是否匹配一个'List [String]'或者你在真实代码中有更复杂的结构吗?在任何情况下,标识符名称在这里都不是很相关,因为所有元素都是相同类型的(不是HList)。最后需要注意的是 - 你必须在上面放置更多匹配元素,否则Scala将永远不会匹配你的案例3,因为案例2匹配它 - 反向引用在这里可以帮助匹配特定值,但是要谨慎 –

回答

3
val `namespace` = "namespace" 
val `elementTerminator` = "elementTerminator" 
val `openBracket` = "openBracket" 
val `closeBracket` = "closeBracket" 

// list of partial functions from list of strings to string:  
val patterns = List[PartialFunction[List[String], String]](
    { case `namespace` :: value :: `elementTerminator` :: rest => "case1" }, 
    { case `openBracket` :: rest => "case2" }, 
    { case `closeBracket` :: `elementTerminator` :: rest => "case3" }) 

def matchingAndDispatch(xs: List[String], patterns: List[PartialFunction[List[String], String]]): String = { 
    patterns.find(_.isDefinedAt(xs)).map(_(xs)).getOrElse("unknown") 
} 

测试:

matchingAndDispatch(List("namespace", "somevalue", "elementTerminator"), patterns) 
> case1 

matchingAndDispatch(List("namespace", "somevalue", "elementTerminator", "more"), patterns) 
> case1 

matchingAndDispatch(List("namespace", "somevalue", "not_terminator", "more"), patterns) 
> unknown 
+0

I认为这会做到这一点,非常感谢! –

0

可以在本地范围内声明一个稳定的标识符。也就是说,你可以写

val hd = matchingClauses.head 
xs match { 
    case `hd` => ??? 
}