179
4
패턴 매칭
4.2
매치 내의 값, 변수, 타입
종류의 매치를 살펴보자. 다음 예제는 특정 값이나 특정 타입의 모든 값과 매치시키는
법을 보여주며, 모든 값에 일치하는 ‘기본’ 절을 쓰는 방법 하나를 보여준다.
//
src
/
main
/
scala
/
progscala2
/
patternmatching
/
match
-
variable
.
sc
for
{
x
<
-
Seq
(
1
,
2
,
2
.
7
,
"
one
",
"
two
",
'
four
)
//
}{
val str
=
x match
{
//
case 1
=
>
"
int 1
"
//
case i
:
Int
=
>
"
other int
:
"+
i
//
case d
:
Double
=
>
"
a double
:
"+
x
//
case
"
one
"
=
>
"
string one
"
//
case s
:
String
=
>
"
other string
:
"+
s
//
case unexpected
=
>
"
unexpected value
:
"
+
unexpected
//
}
println
(
str
)
//
}
여러 타입의 값이 섞여 있기 때문에
Seq
[
Any
]
타입의 목록을 사용한다.
x
Any
타입이다.
x
1
경우 일치한다.
다른
Int
값과 일치한다. 안전하게
x
값을
Int
변환하고,
i
대입한다.
모든
Double
값과 일치한다. 경우
x
값을
Double
변수
d
대입한다.
문자열
one
’과 일치한다.
다른 문자열과 일치한다. 경우
x
값을
String
변수
s
대입한다.
모든 다른 입력값과 일치한다. 경우
unexpected
x
값을 대입할 변수 이름이다. 타입
표기하지 않았기 때문에
Any
타입을 추론한다. 절이 기본역할을 한다.
돌려받은 문자열을 출력한다.
180
2
기본기 다지기
알아보기 쉽게
=
>
(화살표)중심으로 정렬했다. 다음은 출력이다.
int 1
other int
:
2
a double 2
.
7
string one
other string
:
two
unexpected value
:
'
four
다른 모든 식과 마찬가지로 매치식도 값을 반환한다. 여기서는 모든 절이 문자열을 반환한다.
따라서 전체
match
문의 결과 타입도
String
이다. 컴파일러는 모든
case
절이 반환하는 값의
가장 가까운 슈퍼타입 (다른 말로 최소 상위 바운드
least
upper
bound
라고 한다 )추론한다.
x
Any
타입이기 때문에, 값이 취할 수 있는 모든 경우를 처리할 있는
case
절이 필요하다
(
Boolean
값에 대해 매치시켰던 번째 예제와 비교해보라 ). 그래서 ‘기본’ (
unexpected
있는 부분 )있어야 한다. 하지만
PartialFunction
만들 때는 가능한 일부분만 처리
하는 것이 의도이기 때문에, 모든 가능한 값에 대해 매치시킬 필요는 없다.
매치는 앞에서부터 차례대로 처리된다. 따라서 더 구체적인 절이 덜 구체적인 절 앞에 나와야
한다. 그렇지 않으면 더 구체적인 절은 결코 매치를 시도할 대상이 없다. 따라서 기본
가장 마지막에 와야 한다. 다행히 컴파일러가 이런 오류를 잡아준다.
부동소수점 리터럴과 매치시키는 것은 좋은 생각이 아니기 때문에, 부동소수점 리터럴을 처리하
는 절을 포함시키지 않았다. 소수에서 가장 작은 자릿수가 다른데도 반올림 오류
rounding
error
수가 같아질 있기 때문이다.
다음은 앞의 예제를 조금 바꾼 것이다.
//
src
/
main
/
scala
/
progscala2
/
patternmatching
/
match
-
variable2
.
sc
for
{
x
<
-
Seq
(
1
,
2
,
2
.
7
,
"
one
",
"
two
",
'
four
)
}{
val str
=
x match
{
case 1
=
>
"
int 1
"
181
4
패턴 매칭
case
_
:
Int
=
>
"
other int
:
"+
x
case
_
:
Double
=
>
"
a double
:
"+
x
case
"
one
"
=
>
"
string one
"
case
_
:
String
=
>
"
other string
:
"+
x
case
_
=
>
"
unexpected value
:
"
+
x
}
println
(
str
)
}
i
,
d
,
s
unexpected
변수를 위치지정자(
_
)바꿨다. 문자열을 만들 것이기 때문에, 실제로
각각의 타입에 따른 실제값을 만들 필요가 없다. 따라서 모든 경우에
x
사용할 있다.
TIP
PartialFunction
아닌 경우, 매치는 완전해야 한다. 입력이
Any
타입이라면 마지막에
case
_
case
변수
_
이름
처럼 기본 절을 추가하라.
case
절을 작성할 염두에 두어야 가지 규칙과 미묘한 부분이 있다. 컴파일러는
case
음에 대문자로 시작하는 이름이 오면 타입 이름으로 간주한다. 소문자로 시작하는 이름은 매치
또는 추출
extract
값을 담을 변수로 취급한다.
규칙은 때로 놀라움을 선사한다. 아래 예를 보자.
//
src
/
main
/
scala
/
progscala2
/
patternmatching
/
match
-
surprise
.
sc
def checkY
(
y
:
Int
)
=
{
for
{
x
<
-
Seq
(
99
,
100
,
101
)
}{
val str
=
x match
{
case y
=
>
"
found y
!"
case i
:
Int
=
>
"
int
:
"+
i
}
println
(
str
)
}
}
checkY
(
100
)
182
2
기본기 다지기
case
절에서 처리할 값을 하드코딩하기보다는 함수의 인자로 받고 싶었다.
x
100
경우
y
값과 일치하기 때문에(
y
에는 인자로 받은
100
들어 있다), 다음과 같은 결과가 나오리라 예상
했을 수도 있다.
int
:
99
found y
!
int
:
101
하지만 다음이 실제로 있는 출력이다.
<
console
>
:
12
:
warning
:
patterns after a variable pattern cannot match
(
SLS 8
.
1
.
1
)
If you intended to match against parameter y of method checkY
,
you must use
backticks
,
like
:
case
`
y
`
=
>
case y
=
>
"
found y
!"
^
<
console
>:
13
:
warning
:
unreachable code due to variable pattern
'
y
'
on line 12
case i
:
Int
=
>
"
int
:
"+
i
^
<
console
>:
13
:
warning
:
unreachable code
case i
:
Int
>
"
int
:
"+
i
^
checkY
:
(
y
:
Int
)
Unit
found y
!
found y
!
found y
!
case
y
는 실제로는 (타입 표기가 없기 때문에) 어떤 것이든 일치시켜서 그 값을
y
라는
수에 대입하라’는 뜻이다. 여기서
y
메서드 인자
y
가리키는 것으로 해석되지 않는다. 따라
서 실제로 우리는 모든 것을 다 잡아내는 기본 절을 정의한 것이고, 그로 인해 이 변수 패턴
모든 것을 잡아내어 번째
case
식에 도달할 없다는 경고가 발생한다. 코드에 도달할
없다는 오류를 있다. ‘
SLS
8
.
1
.
1
’은 스칼라 언어 명세
The
Scala
Language
Specification
8
.
1
.
1
절을 가리킨다 (
http
://
bit
.
ly
/
1wNBOR8
).
오류 메시지는 우리가 취해야 할 조치,
y
들어 있는 값에 대해 매치를 수행하고 싶다면
역작은따옴표’사용해야 한다는 것을 알려준다.

Get 프로그래밍 스칼라: 실용적인 스칼라 활용법을 익히는 가장 확실한 실전 바이블 (2.11.x 버전 기반) now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.