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") 

인가 이 목적을 달성 할 스칼라 API에는 무엇이 있을까요? 나는 아무것도 발견하지 못했다. 아니면 내가 잘못된 방향으로 가고 있을까요?

+0

파서 Combinators를 사용하면 괜찮을지도 모릅니다. 단순히 문맥 자유 문법을 정의하면 Scala가 나머지를 처리합니다. 실제로 List [String]과 매치되거나 실제 코드에서 더 복잡한 구조를 가지고 있습니까? 두 경우 모두 식별자 이름은 모든 요소가 동일한 유형 (HList 아님)이기 때문에 여기서는별로 관련이 없습니다. 마침내주의 사항 - 더 많은 요소가 일치하는 사례를 상단에 놓아야합니다. 그렇지 않으면 스칼라는 케이스 2가 예제와 일치하기 때문에 예제 3과 일치하지 않습니다. - 백틱은 특정 값과 일치하도록 도와줍니다. 그러나주의해야합니다. –

답변

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` => ??? 
} 
관련 문제