Skip to content
QyuStory edited this page Sep 25, 2016 · 2 revisions

for 내장 : 내부 동작

  • for 내장 문법은 컴파일러에 의해 제공되는 컬렉션 메서드인 foreach, map, flatMap 그리고 withFilter등을 더 쉽게 표현하는 방법이다.

  • 단순하지 않은 연쇄호출의 경우 for 내장은 API를 부르는 것보다 읽고 쓰기 훨씬 편하기 때문이다.

  • filter와 달리, 메서드 withFilter는 컬렉션을 만들어내지 않는다.

  • for 내장이 어떻게 메서드 호출을 대신하는지 살펴보기 위해 몇가지 간단한 비교를 해보자.

// src/main/scala/progscala2/forcomps/for-foreach.sc

val states = List("Alabama", "Alaska", "Virginia", "Wyoming")

for {
  s <- states
} println(s)
// Results:
// Alabama
// Alaska
// Virginia
// Wyoming

states foreach println
// Results the same as before.

for 내장 후 yield표현이 없는 단일 제너레이터 표현은 collection의 foreach에 해당한다.

// src/main/scala/progscala2/forcomps/for-map.sc

val states = List("Alabama", "Alaska", "Virginia", "Wyoming")

for {
  s <- states
} yield s.toUpperCase
// Results: List(ALABAMA, ALASKA, VIRGINIA, WYOMING)

states map (_.toUpperCase)
// Results: List(ALABAMA, ALASKA, VIRGINIA, WYOMING)

yield를 함께 사용한 단일 제너레이터 표현은 map에 해당한다. yield가 사용될 경우 새로운 컨테이너를 만든다. 이 때, 첫번째 제너레이터 표현의 타입이 마지막 결과 컬렉션의 타입을 결정한다.

  • 하나 이상의 제너레이터가 있을 경우
// src/main/scala/progscala2/forcomps/for-flatmap.sc

val states = List("Alabama", "Alaska", "Virginia", "Wyoming")

for {
  s <- states
  c <- s
} yield s"$c-${c.toUpper}"
// Results: List("A-A", "l-L", "a-A", "b-B", ...)

states flatMap (_.toSeq map (c => s"$c-${c.toUpper}"))
// Results: List("A-A", "l-L", "a-A", "b-B", ...)

두번째 제너레이터(c <- s)는 String s에 있는 각각의 캐릭터들을 반복해서 넣어준다. yield 문장은 캐릭터와 그 캐릭터의 대문자를 '-'에 의해 분리하여 리턴한다.

  • if를 이용하여 가드를 만든 경우
// src/main/scala/progscala2/forcomps/for-guard.sc

val states = List("Alabama", "Alaska", "Virginia", "Wyoming")

for {
  s <- states
  c <- s
  if c.isLower
} yield s"$c-${c.toUpper} "
// Results: List("l-L", "a-A", "b-B", ...)

states flatMap (_.toSeq withFilter (_.isLower

withFilter의 경우 마지막 map 전에 사용한다.

  • 변수를 정의한 경우
// src/main/scala/progscala2/forcomps/for-variable.sc

val states = List("Alabama", "Alaska", "Virginia", "Wyoming")

for {
  s <- states
  c <- s
  if c.isLower
  c2 = s"$c-${c.toUpper} "
} yield c2
// Results: List("l-L", "a-A", "b-B", ...)

states flatMap (_.toSeq withFilter (_.isLower) map { c =>
  val c2 = s"$c-${c.toUpper} "
  c2
})
// Results: List("l-L", "a-A", "b-B", ...)
Clone this wiki locally