De-Note sparkafka's dev blog

[Scala] for 문에 대하여

들어가며

Coursera Scala 강의를 다시 듣기 시작하였다. 이 코스는 작년에 들었던 코스의 다음 내용인데, scala를 워낙 가끔씩만 보다 보니 지난 강의의 내용이 기억이 잘 나지 않는다. 복습으로 for에 대한 내용이 나왔는데, 잘 기억이 나지 않아서 다시 정리하는 것이 좋다고 생각하였다.

For-Expressions

나의 작년 게시글에서 for 문을 보통 collection을 조회하는 데에 쓰인다고 적었다. 지금 다시 봤는데, 부족한 설명인 것 같아서 요즘 나의 친구 ChatGPT에 물어보았다.

chatgpt_for

오… scala에서 for 문은 collection에 연산을 수행하기 위한 synthetic sugar이고, collection에 일련의 연산을 수행한 뒤 새로운 collection을 결과값으로 반환한다고 한다.

기본적인 구조는 다음과 같다.

for (enumerator) yield expression

기본적으로 python의 for문과 상당히 유사하다. enumerator는 element와 처리될 collection이고 expression은 각 element에 실행될 연산이다. 저 연산의 결과로 새로운 collection이 반환된다.

1부터 9까지의 짝수 요소에 2를 곱한 결과 collection을 얻고 싶다면 다음과 같이 for 문을 쓸 수 있다.

for (x <- 1 until 10 if x % 2 == 0) yield x * 2

그런데 위에서 for 문은 collection에 연산을 수행하기 위한 synthetic sugar라고 하였다. 사실 scala에서 for문은 map, filter, flatMap과 같은 collection 연산들을 이해하기 쉽게 만든 표현이다. scala에서도 for 문을 컴파일할 때 collection 연산으로 해석하여 수행한다고 한다. 따라서 위 구문도 collection 연산으로 바꿔서 쓸 수 있다.

(1 until 10).withFilter(x => x % 2 == 0).map(x => x * 2)

withFilter는 중간 collection을 생성하지 않고 다음 연산에 filter 결과물을 넘겨주는 연산이다.

scala에서는 method 연산에서 ‘.’을 생략할 수 있으므로 다음과 같이 표현할 수 있다.

(1 until 10) withFilter (x => x % 2 == 0) map (x => x * 2)

아래는 for문 해석 규칙이다.

1.
for (x <- e1) yield e2
e1.map(x => e2)

2.
for (x <- e1 if f; s) yield e2
for (x <- e1.withFilter(x => f); s) yield e2

3.
for (x <- e1; y <- e2; s) yield e3
e1.flatMap(x => for (y <- e2; s) yield e3)

s: sequence of generators and filters(potentially empty)

여기서 s는 계속 이어지는 표현들이다. 가장 안 쪽의 collection은 map을 수행하고, 나머지 바깥쪽의 collection들은 flatMap을 수행한다. 조건문이 있는 경우 filter를 사용한다.

적용

만약 구구단에서 뒤 숫자가 짝수인 경우의 결과만 얻고싶다면 다음과 같이 for 문을 쓸 수 있다.

for (x <- 2 to 9; y <- 1 to 9 if y % 2==0) yield (x, y, x * y)

이 것을 collection 연산으로 바꿔보자.

(2 to 9) flatMap (x => 
  (1 to 9) withFilter (y => y % 2 == 0) map (y => (x, y, x * y)))

결과는 다음과 같다.

for

collection operations

두 결과가 동일한 것을 확인하였다.

마치며

오랜만에 scala를 봐서 처음엔 조금 힘들었는데 하다보니 기억이 새록새록 떠올라서 다행이었다. 또 기억 안 나는 부분은 ChatGPT를 이용했는데, 아주 큰 도움이 되었다. map, flatMap, filter에 대한 복습도 돼서 좋았다. 지금까지는 공부한 내용을 계속 잊고 있는데, 계속 꾸준히 해서 공부한 내용을 최대한 많이 기억해야 할 것이다.