ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 스칼라의 패턴 매칭
    컴공지식/프로그래밍언어론 2024. 8. 31. 22:41

    패턴 매칭은 스칼라에서 매우 강력하고 유용한 기능 중 하나이다.

    이걸 잘 이해하면 코드를 훨씬 간결하고 직관적으로 작성할 수 있다.

     

    패턴 매칭은 주어진 값이나 표현식(expr)을 여러 패턴(case variant_id)과 비교해서, 어떤 패턴과 일치하는지에 따라 특정 코드를 실행하는 기능이다.

    스칼라에서 흔히 쓰이는 match 키워드를 이용해 이런 패턴 매칭을 구현할 수 있다.

     

    기본 구조는 다음과 같다

     

    expr match {
      case variant_id1 (field_id11, ...) => expr1
      ...
      case variant_idm (field_idm1, ...) => exprm
    }

     

    expr: 여기에는 매칭할 표현식이나 값이 들어간다.

    match: 패턴 매칭을 시작하는 키워드야. expr의 값을 여러 case와 비교한다.

    case variant_id (field_id, ...) => expr: 각 case는 하나의 패턴을 의미한다. expr의 값이 case에서 지정한 패턴과 일치하면, 그 뒤의 표현식(=> expr)이 실행된다.

     

    이전에 예시로 들었던 이것이 패턴 매칭을 이용한 것이다.

     

    def describeShape(shape: Shape): String = shape match {
      case Triangle(a, b, c) => s"Triangle with sides $a, $b, $c"
      case Rectangle(h, w) => s"Rectangle with height $h and width $w"
      case Square(side) => s"Square with side $side"
    }

     

    패턴 매칭을 사용하면 복잡한 조건문(if-else) 없이도 간단하고 읽기 쉬운 코드를 작성할 수 있다.

    스칼라는 패턴 매칭에서 모든 가능한 경우를 다루고 있는지 자동으로 확인한다.

    만약 빠뜨린 경우가 있다면 컴파일러가 경고를 해준다.

    코드에서 도달할 수 없는 패턴이 있다면, 컴파일러가 알려준다.

    이 덕분에 불필요한 코드가 들어가지 않게 되고, 논리적인 오류도 미리 방지할 수 있다.

    그렇기 때문에 디버깅에 유리하다.

     

     

    다음 예시도 한 번 살펴보자

     

    // perimeter: Shape => Int
    def perimeter(sh: Shape): Int = sh match {
      case Triangle(a, b, c) => a + b + c
      case Rectangle(h, w) => 2 * (h + w)
      case Square(s) => 4 * s
      case _ => -1
    }

    @main def run(): Unit = {
      println(perimeter(Triangle(3, 4, 5)))  // result: 12
      println(perimeter(null))               // result: -1
    }

    // 도형들을 정의하기 위해 필요한 case class와 trait들
    trait Shape

    case class Triangle(a: Int, b: Int, c: Int) extends Shape
    case class Rectangle(h: Int, w: Int) extends Shape
    case class Square(side: Int) extends Shape

     

    perimeter 함수는 Shape 타입의 sh라는 매개변수를 받아서, Int 타입의 값을 반환한다. 즉, 도형의 둘레를 계산해서 정수로 반환하는 함수다.

    sh match { ... }: 이 부분에서 패턴 매칭을 사용해 sh가 어떤 도형인지 확인하고, 그에 따라 둘레를 계산한다.

    case _ => -1 는 위의 세 패턴과 매칭되지 않는 모든 경우를 처리한다.

    _는 "어떤 값이든지"를 의미한다.

    이 경우 -1을 반환하여 예상치 못한 값이 들어왔을 때를 처리할 수 있다.

     

    run 함수는 프로그램의 진입점이다. 여기서 perimeter 함수를 호출해서 결과를 출력한다.

    Triangle 패턴에 따라 3 + 4 + 5 = 12로 계산되어 12가 출력된다.

    만약 null 값을 넣으면, 위에서 정의한 세 가지 패턴과는 매칭되지 않아서 -1이 출력된다.

     

     

    또 다른 예시도 살펴보자

     

    def interestRate(amount: Double): Double = amount match {
      case x if x <= 1000 => 0.040
      case x if x <= 5000 => 0.045
      case x if x > 5000 => 0.050
    }

     

    이 함수는 amount라는 Double 타입의 예금액을 입력으로 받아서, 해당하는 이자율을 Double 타입으로 반환하는 함수이다.

    즉, 예금액(amount)에 따라 이자율을 결정해준다.

    예금액 x가 $1,000 이하일 때, 4% 이자율을 반환하고, $1,000 초과 $5,000 이하일 때, 4.5% 이자율을 반환한다. 그리고 예금액 x가 $5,000 초과일 때, 5% 이자율을 반환한다.

     

    x는 amount의 값을 의미하는 임시 변수다.

    패턴 매칭에서 case x를 사용하면, x는 amount와 동일한 값이 된다.

    만약 x가 없이 그냥 case amount if amount <= 1000 => 0.040처럼 쓸 수도 있지만, x를 쓰면 코드가 좀 더 간결해 보일 수 있다.

    변수명은 x든 z든 상관없다. 그냥 편한 이름으로 바꿔서 쓸 수 있다.

    중요한 건 그 변수명이 amount의 값을 가리키고, 조건을 검사하는 데 사용된다는 거다.

     

     

     

Designed by Tistory.