복붙노트

[SCALA] 스칼라 : 패턴 매칭의 짧은 형식 부울을 반환

SCALA

스칼라 : 패턴 매칭의 짧은 형식 부울을 반환

나는 나 자신이 이런 일을 자주 쓰기 발견 :

a match {     
  case `b` => // do stuff
  case _ => // do nothing
}

일부 값이 패턴과 일치하는지 확인하기 위해 짧은 방법이 있나요? 나는,이 경우에는 그냥 쓸 수있는 의미있는 경우 (A == 나) // 물건을, 패턴이 더 복잡하면 어떻게? 목록 또는 임의의 복잡도의 어떤 패턴과 일치하는 경우 등을들 수있다. 나는 이런 식으로 뭔가를 쓸 수 있도록하고 싶습니다 :

if (a matches b) // do stuff

내가 뭔가 큰를 누락하는 경우, 그래서 용서하시기 바랍니다, 스칼라 비교적 새로운 해요 :)

해결법

  1. ==============================

    1.나는 아무도 그들을 언급되지 않았기 때문에 분명히 감동 모호하다 이러한 기능을 쓴 이유는 정확히이다.

    나는 아무도 그들을 언급되지 않았기 때문에 분명히 감동 모호하다 이러한 기능을 쓴 이유는 정확히이다.

    scala> import PartialFunction._
    import PartialFunction._
    
    scala> cond("abc") { case "def" => true }
    res0: Boolean = false
    
    scala> condOpt("abc") { case x if x.length == 3 => x + x }
    res1: Option[java.lang.String] = Some(abcabc)
    
    scala> condOpt("abc") { case x if x.length == 4 => x + x }
    res2: Option[java.lang.String] = None
    
  2. ==============================

    2.기능적인 스타일에서 사용할 때 스칼라에서 경기 연산자는 가장 강력하다. 이 수단은 오히려 경우 문에서 "일을"보다, 당신은 유용한 값을 반환합니다. 여기에 필수적 스타일에 대한 예입니다 :

    기능적인 스타일에서 사용할 때 스칼라에서 경기 연산자는 가장 강력하다. 이 수단은 오히려 경우 문에서 "일을"보다, 당신은 유용한 값을 반환합니다. 여기에 필수적 스타일에 대한 예입니다 :

    var value:Int = 23
    val command:String = ... // we get this from somewhere
    command match {
      case "duplicate" => value = value * 2
      case "negate" => value = -value
      case "increment" => value = value + 1
      // etc.
      case _ => // do nothing
    }
    println("Result: " + value)
    

    superflous 것 때문에이 위가 조금 아파 "아무것도하지 않는"매우 이해할 수있다. 그러나,이 때문에 위가 필수적 스타일로 작성된다는 사실이다. 이와 같은 구조는 때때로해야 할 수도 있지만, 많은 경우에 당신은 기능적인 스타일로 코드를 리팩토링 할 수 있습니다 :

    val value:Int = 23
    val command:String = ... // we get this from somewhere
    val result:Int = command match {
       case "duplicate" => value * 2
       case "negate" => -value
       case "increment" => value + 1
       // etc.
       case _ => value
    }
    println("Result: " + result)
    

    이 경우, 당신은 당신이, 예를 들어, 변수에 할당 할 수있는 값으로 전체 매치 문을 사용합니다. 그리고 경기 문이 어떤 경우에 값을 반환해야하는 것이 훨씬 더 분명하다; 마지막 경우 누락 될 경우, 컴파일러는 뭔가를 만들 수 없습니다.

    그것은 취향의 문제이지만, 일부 개발자들은이 스타일이 더 투명하고 더 실제 사례에서 쉽게 처리 할 수 ​​생각. 내가 스칼라 프로그래밍 언어의 발명자가 일치 마음에 더 많은 기능 사용을 한 것으로 나타 내기 것이고, 당신은 단지 특정 행동의 요구를 취할 것인지 여부를 결정해야하는 경우 실제로 문은 더 이해하게합니다. (그것은 또한 반환 값을 가지고 있기 때문에 다른 한편으로는, 당신은 또한 ..., 기능적인 방법으로 경우에 사용할 수 있습니다)

  3. ==============================

    3.이 힘 도움말 :

    이 힘 도움말 :

    class Matches(m: Any) {
        def matches[R](f: PartialFunction[Any, R]) { if (f.isDefinedAt(m)) f(m) }
    }
    implicit def any2matches(m: Any) = new Matches(m)
    
    scala> 'c' matches { case x: Int => println("Int") }                                
    
    scala> 2 matches { case x: Int => println("Int") }  
    Int
    

    이제 문제의 일반적인 성격에 약간의 설명.

    발, 케이스를위한 세 가지 패턴 매칭이 발생할 수있는 장소가있다. 그들에 대한 규칙은 다음과 같습니다

    // throws an exception if it fails
    val pattern = value 
    
    // filters for pattern, but pattern cannot be "identifier: Type",
    // though that can be replaced by "id1 @ (id2: Type)" for the same effect
    for (pattern <- object providing map/flatMap/filter/withFilter/foreach) ...
    
    // throws an exception if none of the cases match
    value match { case ... => ... }
    

    기능과 부분적인 기능 리터럴 인 경우 나타날 수있는 또 다른 상황은, 그러나,있다. 예를 들면 :

    val f: Any => Unit = { case i: Int => println(i) }
    val pf: PartialFunction[Any, Unit] = { case i: Int => println(i) }
    

    경우 문 일치하지 않는 인수로 호출하면 두 함수와 부분적인 기능 예외가 발생합니다. 그러나, 일부 기능들은 또한 매칭이 이루어질 여부 될 수 있는지를 테스트 할 수 isDefinedAt라는 방법을 제공뿐만 아니라 기능에 PartialFunction [T, R]를 설정한다 리프트라고 불리는 방법으로서 [T, 옵션 [R] ] 의미 비 매칭 값 없음 대신 예외 발생 될 것이다.

    일치가 여러 가지 시험의 조합입니다 :

    // assign anything to x
    case x
    
    // only accepts values of type X
    case x: X
    
    // only accepts values matches by pattern
    case x @ pattern
    
    // only accepts a value equal to the value X (upper case here makes a difference)
    case X
    
    // only accepts a value equal to the value of x
    case `x`
    
    // only accept a tuple of the same arity
    case (x, y, ..., z)
    
    // only accepts if extractor(value) returns true of Some(Seq()) (some empty sequence)
    case extractor()
    
    // only accepts if extractor(value) returns Some something
    case extractor(x)
    
    // only accepts if extractor(value) returns Some Seq or Tuple of the same arity
    case extractor(x, y, ...,  z)
    
    // only accepts if extractor(value) returns Some Tuple2 or Some Seq with arity 2
    case x extractor y
    
    // accepts if any of the patterns is accepted (patterns may not contain assignable identifiers)
    case x | y | ... | z
    

    이제 추출기 방법이 적용된 또는 unapplySeq, 제 복귀 부울 또는 옵션 [T]과 중에 일치가 이루어지지 않음을 의미 제 복귀 옵션 [서열 [T], 일부 (결과) 결과와 일치하는 것을 시도 할 것이다 상기와 같이 설명했다.

    그러니 그냥 패턴 일치가 발생할 수 있습니다 세 가지 구성 중 하나를 사용하지 않고 할 수 없습니다 여기에 구문 대안의 모든 종류가 있습니다. 당신은 할 수 있지만 그들 모두의 가치 평등과 추출기와 같은 일부 기능을 모방 할 수 있습니다.

  4. ==============================

    4.패턴은 표현식에서 사용할 수 있습니다. 귀하의 코드 샘플

    패턴은 표현식에서 사용할 수 있습니다. 귀하의 코드 샘플

    a match {     
      case b => // do stuff
      case _ => // do nothing
    }
    

    다음과 같이 표현 될 수있다

    for(b <- Some(a)) //do stuff
    

    트릭은이 유효한 열거 할 래핑하는 것입니다. 예를 들면 목록 (A) 작업도 것이지만, 일부 (a)는 의도 한 의미에 가장 가까운 생각합니다.

  5. ==============================

    5.내가 가지고 올 수있는 최선은 이것이다 :

    내가 가지고 올 수있는 최선은 이것이다 :

    def matches[A](a:A)(f:PartialFunction[A, Unit]) = f.isDefinedAt(a)
    
    if (matches(a){case ... =>}) {
        //do stuff
    }
    

    하지만 이것은 당신에게 어떤 스타일의 포인트를 이길 것입니다.

  6. ==============================

    6.김의 대답은 더 나은 귀하의 요구 사항에 맞게 "개선"할 수 있습니다 :

    김의 대답은 더 나은 귀하의 요구 사항에 맞게 "개선"할 수 있습니다 :

    class AnyWrapper[A](wrapped: A) {
      def matches(f: PartialFunction[A, Unit]) = f.isDefinedAt(wrapped)
    }
    implicit def any2wrapper[A](wrapped: A) = new AnyWrapper(wrapped)
    

    그때:

    val a = "a" :: Nil
    if (a matches { case "a" :: Nil => }) {
      println("match")
    }
    

    나는 그러나, 그것을 할 것입니다. 는 =>}) {순서는 여기에 정말 못생긴, 전체 코드는 훨씬 덜 분명 정상적인 경기보다는 보인다. 게다가, 당신은 문자열에서처럼하지 다른, 이미 정의 일치 방법으로 얻을 수있는 충돌을 계산 (A PartialFunction에서 경기를 포장의 오버 헤드 암시 적 변환을 찾고의 컴파일 타임 오버 헤드 및 런타임을 얻을 ).

    조금 더 나은 모습 (덜 장황), 당신은 AnyWrapper에 데프이를 추가 할 수 있습니다 :

    def ifMatch(f: PartialFunction[A, Unit]): Unit = if (f.isDefinedAt(wrapped)) f(wrapped)
    

    이 같이 사용할 수 :

    a ifMatch { case "a" :: Nil => println("match") }
    

    이는 매우 좋은하지 ... 당신은 _ => 라인 귀하의 경우 저장하지만 대신 하나의 명령문 블록을 원하는 경우 이중 중괄호가 필요합니다.

    이 단지 부작용을 가지고 뭔가를 실행하는 데 사용할 수있는이 구조는 함수형 프로그래밍의 정신에 정말 아닙니다. 우리는 쉽게 기능 부분이기 때문에, 값 (그러므로 단위 반환 값)을 반환하는 데 사용할 수 없습니다 - 우리가 기본값이 필요 것, 또는 우리가 옵션 인스턴스를 반환 할 수 있습니다. 우리는 아무 것도 얻을 수없는 것 때문에 그러나 여기서 다시, 우리는 아마, 일치로 포장을 푸는 것이다.

    솔직히, 당신은 더 나은보고 자주 그 일치를 사용하고 (매덕의 좋은 설명은 다음) 필수적 스타일 구조의이 종류에서 멀리 이동에 익숙해 길 이죠.

  7. from https://stackoverflow.com/questions/4437061/scala-short-form-of-pattern-matching-that-returns-boolean by cc-by-sa and MIT license