수색…


통사론

  • 발 추출기 (추출 된 값 1, _ / * 무시 된 두 번째 추출 된 값 * /) = valueToBeExtracted
  • valueToBeExtracted match {case 추출기 (extractedValue1, _) => ???}
  • val (tuple1, tuple2, tuple3) = tupleWith3Elements
  • 객체 Foo {def unapply (foo : Foo) : 옵션 [String] = 일부 (foo.x); }

튜플 추출기

xy 는 튜플에서 추출됩니다.

val (x, y) = (1337, 42)
// x: Int = 1337
// y: Int = 42

값을 무시하려면 _ :을 사용하십시오.

val (_, y: Int) = (1337, 42)
// y: Int = 42

추출기의 포장을 풀려면 다음과 같이하십시오.

val myTuple = (1337, 42)
myTuple._1  // res0: Int = 1337
myTuple._2  // res1: Int = 42

튜플 (22)의 최대 길이를 가질 수 있음을 유의 따라서 ._1 통해 ._22 작동 (튜플을 가정하면, 적어도 그 크기).

튜플 추출기는 리터럴 함수에 대한 기호 인수를 제공하는 데 사용할 수 있습니다.

val persons = List("A." -> "Lovelace", "G." -> "Hopper")
val names = List("Lovelace, A.", "Hopper, G.")

assert {
  names ==
    (persons map { name =>
      s"${name._2}, ${name._1}"
    })
}

assert {
  names ==
    (persons map { case (given, surname) =>
      s"$surname, $given"
    })
}

사례 클래스 추출기

사례 클래스 는 많은 표준 상용구 코드가 자동으로 포함 된 클래스입니다. 이것의 한 가지 이점은 스칼라가 사례 클래스로 추출기를 사용하기 쉽다는 것입니다.

case class Person(name: String, age: Int)  // Define the case class
val p = Person("Paola", 42)  // Instantiate a value with the case class type

val Person(n, a) = p  // Extract values n and a
// n: String = Paola
// a: Int = 42

이 시점에서, na 는 모두 프로그램에서 val 가 있으며 다음과 같이 액세스 할 수 있습니다. 이들은 p에서 '추출'되었다고합니다. 계속 :

val p2 = Person("Angela", 1337)

val List(Person(n1, a1), Person(_, a2)) = List(p, p2)
// n1: String = Paola
// a1: Int = 42
// a2: Int = 1337

여기서 우리는 두 가지 중요한 것을 봅니다 :

  • 추출은 '깊은'수준에서 발생할 수 있습니다. 중첩 된 객체의 속성을 추출 할 수 있습니다.
  • 모든 요소를 ​​추출 해야하는 것은 아닙니다. 와일드 카드 _ 문자는 특정 값이 무엇이든 될 수 있음을 나타내며 무시됩니다. val 생성되지 않습니다.

특히 이것은 콜렉션을 쉽게 매칭시킬 수있다.

val ls = List(p1, p2, p3)  // List of Person objects
ls.map(person => person match {
  case Person(n, a) => println("%s is %d years old".format(n, a))
})

여기서 추출기를 사용하여 personPerson 객체인지 명시 적으로 확인하고 우리가 신경 써야하는 변수 인 na 즉시 추출하는 코드가 있습니다.

적용 취소 - 사용자 정의 추출기

unapply 메서드를 구현하고 Option 유형의 값을 반환하면 사용자 지정 추출을 작성할 수 있습니다.

class Foo(val x: String)

object Foo {
  def unapply(foo: Foo): Option[String] = Some(foo.x)
}

new Foo("42") match {
  case Foo(x) => x
}
// "42"

돌려 주어지는 형태가 getisEmpty 메소드를 제공하는 경우, unapply 의 반환 값의 형태는 Option 이외의 것이 있습니다. 이 예제에서 Bar 는 이러한 메서드로 정의되며 unapplyBar 의 인스턴스를 반환합니다.

class Bar(val x: String) {
  def get = x
  def isEmpty = false
}

object Bar {
  def unapply(bar: Bar): Bar = bar
}

new Bar("1337") match {
  case Bar(x) => x
}
// "1337"

unapply 의 반환 유형은 Boolean 될 수도 있습니다.이 Boolean 은 위의 getisEmpty 요구 사항을 수행하지 않는 특별한 경우입니다. 그러나이 예제에서 DivisibleByTwo 는 클래스가 아닌 객체이며 매개 변수를 취하지 않으므로 (해당 매개 변수를 바인딩 할 수 없음) 유의하십시오.

object DivisibleByTwo {
  def unapply(num: Int): Boolean = num % 2 == 0
}

4 match {                        
  case DivisibleByTwo() => "yes" 
  case _ => "no"
}
// yes

3 match {
  case DivisibleByTwo() => "yes"
  case _ => "no"
}
// no

unapply 는 클래스가 아닌 클래스의 동반 오브젝트에 unapply 된다는 점을 기억하십시오. 이 구별을 이해하면 위의 예가 분명해질 것입니다.

추출기 삽입 표기법

사례 클래스에 정확히 두 개의 값이있는 경우 해당 추출기를 중침 표기법으로 사용할 수 있습니다.

case class Pair(a: String, b: String)
val p: Pair = Pair("hello", "world")
val x Pair y = p
//x: String = hello
//y: String = world

2-tuple을 반환하는 추출기는이 방법으로 작동 할 수 있습니다.

object Foo {
    def unapply(s: String): Option[(Int, Int)] = Some((s.length, 5))
}
val a Foo b = "hello world!"
//a: Int = 12
//b: Int = 5

정규식 추출기

그룹화 된 부분이있는 정규 표현식을 추출기로 사용할 수 있습니다.

scala> val address = """(.+):(\d+)""".r
address: scala.util.matching.Regex = (.+):(\d+)

scala> val address(host, port) = "some.domain.org:8080"
host: String = some.domain.org
port: String = 8080

일치하지 않으면 런타임에 MatchError 가 발생합니다.

scala> val address(host, port) = "something not a host and port"
scala.MatchError: something not a host and port (of class java.lang.String)

변형 추출기

추출기 동작은 입력에서 임의의 값을 도출하는 데 사용될 수 있습니다. 이는 변환이 성공한 경우 변환 결과에 대해 조치를 취할 수있는 시나리오에서 유용 할 수 있습니다.

Windows 환경에서 사용할 수 있는 다양한 사용자 이름 형식 의 예를 생각해보십시오.

object UserPrincipalName {
  def unapply(str: String): Option[(String, String)] = str.split('@') match {
    case Array(u, d) if u.length > 0 && d.length > 0 => Some((u, d))
    case _ => None
  }        
}

object DownLevelLogonName {
  def unapply(str: String): Option[(String, String)] = str.split('\\') match {
    case Array(d, u) if u.length > 0 && d.length > 0 => Some((d, u))
    case _ => None
  }
}

def getDomain(str: String): Option[String] = str match {
  case UserPrincipalName(_, domain) => Some(domain)
  case DownLevelLogonName(domain, _) => Some(domain)
  case _ => None
}

사실 일치시킬 수있는 유형을 확장하여 두 가지 동작을 모두 보여주는 추출기를 만들 수 있습니다.

object UserPrincipalName {
  def unapply(obj: Any): Option[(String, String)] = obj match {
    case upn: UserPrincipalName => Some((upn.username, upn.domain))
    case str: String => str.split('@') match {
      case Array(u, d) if u.length > 0 && d.length > 0 => Some((u, d))
      case _ => None
    }
    case _ => None
  }        
}

일반적으로 추출기는 tryParse 와 같은 이름을 가진 메소드에 적용되는 Option 패턴의 편리한 재구성입니다.

UserPrincipalName.unapply("user@domain") match {
  case Some((u, d)) => ???
  case None => ???
}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow