1

スカラを使用すると、パターンマッチングするリストパターンを動的に構築する方法はありますか?例えばスカラパターンマッチのダイナミックな安定な識別子

、私はこのように、に解析文字列のリストを安定した識別子を使用していたとします。今

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... 
    } 
} 

、ケース条項の多くがあるように予定されていると仮定し、I実行時に変更できる何らかのコレクションにそれらを格納する機能を必要としました。必ずしもパターン自体ではなく、パターンのコレクションを変更することができます。私は心の中で持っているもの、多かれ少なかれ説明するために、以下のコードで架空のクラス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ではなく)であるため、識別子名はあまり関係しません。最後に注意してください - より多くの要素が一致するケースを先頭に置く必要があります。そうでない場合、ケース2はケース2と一致するため、Scalaはケース3とマッチしません - backticksは特定の値とマッチするためにここで助けます。 –

答えて

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` => ??? 
} 
関連する問題