for
키워드를 사용할 수 있다.for
도 반복문(statement)로 사용할 수 있고 반복식(expression)으로 사용할 수 있다.for
를 사용하면 리턴값이 있을 수 있구나 라고 생각하자.아래의 예시들에서 사용할 컬렉션을 먼저 만들어 보자.
val nums: List[Int] = List(1,2,3,4,5)
참고) Scala 에서는 컬렉션을 만들 때 Mutable(변경가능)한 Array 보다 Immutable(변경불가능)한 Seq 또는 List 사용이 권장된다.
For loop 은 화살표 <-
를 사용해서 컬렉션 내의 요소들을 각각 처리할 수 있다.
// "nums" list 의 요소들을 각자 처리해줍니다
for (num <- nums) println(num)
// 출력:
// 1
// 2
// 3
// 4
// 5
for each
는 for
와 같은 기능을 하지만 조금 더 사람에 익숙한 언어로 표현한 방법이다..
nums.foreach(println)
// 출력:
// 1
// 2
// 3
// 4
// 5
val numbers = Map(
"one" -> 1,
"two" -> 2,
"three" -> 3
)
for ((key, value) <- numbers) println(s"Number $key : $value")
/**
* 출력
* Number one (1)
* Number two (2)
* Number three (3)
*/
이전에 언급했듯이 for
은 문장이 아닌 식으로 사용할 수 있다.
이전까지의 for-loop
는 println
과 같은 side effect*를 위해서 사용되었다면 for-expression
은 기존 컬렉션(List/Array 같은)으로부터 새로운 컬렉션을 만들 때 유용하게 쓰인다.
for
을 식으로 사용하기 위해서는 yield
(뜻: 생성)이란 키워드를 알아야 한다. for loop
가 돌면서 각 요소를 처리한 후 값을 yield (또는 return 이라고 해석해도 무방하다.) 한다.
val doubleNumbers = for (num <- nums) num * 2 // yield 가 없는 것을 주목하자
println(doubleNumbers)
// 출력: ()
// () 는 Scala 에서 Unit 타입 값이다. 리턴값이 없을 때 출력된다.
val doubleNumbersWithYield = for (num <- nums) yield num * 2
println(doubleNumbersWithYield)
// 출력: List(2, 4, 6, 8, 10)
yield
를 사용할 때 복잡한 코드를 for
loop 안에 넣고 싶을 때는 중괄호를 씌워주면 된다.
val someNumbers = for (num <- nums) yield {
val numPlusOne = num + 1
val numMinusOne = num -1
numPlusOne * numMinusOne
}
println(someNumbers)
// 출력: List(0, 3, 8, 15, 24)
여기서 다른 언어들을 다뤄봤다면 (예를 들어 Python), yield 를 중괄호 안에 넣어도 되지 않을까? 라는 생각을 할 수 있다.
val someNumbers = for (num <- nums) {
val numPlusOne = num + 1
val numMinusOne = num -1
yield numPlusOne * numMinusOne // Not allowed!
}
이렇게 하면 yield 후에도 다른 side effect (println
같은)를 처리할 수 있어서 코드가 더 유연해질 수 있겠지만 Scala 에서는 이렇게 사용할 수 없다 (컴파일 에러).
for
직후에 yield
가 와야만 Scala 컴파일러에서 해당 블락이 for-expression 이라는 것을 알고 그에 맞춰 코드를 변환해준다.