for..yield는 for comprehension (sequence comprehension)이라 불린다. 

for.. yield 는 상황에 따라 foreach, flatmap, filter, map으로 translate 할 수 있는 문법 설탕(https://en.wikipedia.org/wiki/Syntactic_sugar)이다.  

개발자가 개발하기 쉽도록 (또는 보기 편하도록) 설계된 문법이다.  


좀 더 재미있는 내용을 살펴보고 싶다면, http://stackoverflow.com/questions/1052476/what-is-scalas-yield를 참조하면 즐거울 것 같다.




예시 시작





그냥 간단한 for문이다.

for(i <- 1 to 3) {
println(i)
}

결과

1

2

3



REPL에서 yield를 사용하면 결과가 Vector 타입의 인스턴스로 리턴한다.

scala> for(i <- 1 to 3) yield i

res2: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3)



val a =  for(i <- 1 to 3) yield i;
println(a)


결과

Vector(1, 2, 3)





yield 값에 곱셈을 추가해본다.

val a =  for(i <- 1 to 3) yield i * 100;
println(a)


결과

Vector(100, 200, 300)





yield 뒤에 조건문을 두어 실행한다.

val a =  for(i <- 1 to 3) yield i > 2;
println(a)

결과

Vector(false, false, true)





yield 앞 for 조건문에 if 문을 둔다. 마치 filter의 효과를 둔다.

val a = for( i <- 1 to 3 ; if i == 1 ) yield i
println(a)

결과

Vector(1)



if 문을 여러 개 두어 필터링을 할 수 있다. 

val a = for( i <- 1 to 3 ; if i == 1 ; if i == 2 ) yield i
println(a)





List를 사용할 수 있고, { }를 이용하여 확장할 수 있다.

val list = List(1, 2, 3)
val a = for {
element <- list
} yield {
element
}
println(a)


결과 

List(1, 2, 3)






앞에서 테스트한 내용을 {}을 이용하여 확장하였다. 결과는 동일하다.

A 코드

val a =  for(i <- 1 to 3) yield i > 2;
println(a)

B 코드


val list = List(1, 2, 3)
val a = for {
i <- list
} yield {
i > 2
}
println(a)


결과

List(false, false, true)





for 문에 List 2개를 넣었다. loop 두 개의 효과가 발생한다.

val list = List(1, 2, 3)
val list2 = List(10, 20)
val a = for {
i <- list
j <- list2
}
yield {
i
}
println(a)


결과

List(1, 1, 2, 2, 3, 3)




val list = List(1, 2, 3)
val list2 = List(10, 20)
val a = for {
i <- list
j <- list2
} yield {
i * j
}
println(a)


결과

List(10, 20, 20, 40, 30, 60)





val list = List(1, 2, 3)
val list2 = List(10, 20)
val list3 = List(1, 2)
val a = for {
i <- list
j <- list2
z <- list3
} yield {
i + j + z
}
println(a)


결과

List(12, 13, 22, 23, 13, 14, 23, 24, 14, 15, 24, 25)







튜플을 만들 수도 있다.


val list = List(1, 2, 3)
val list2 = List("x", "y")
val a = for {
i <- list
j <- list2
} yield {
(i, j)
}
println(a)


결과

List((1,x), (1,y), (2,x), (2,y), (3,x), (3,y))








두 리스트의 엘리먼트를 하나로 합쳐주는 zip 함수를 사용하여 단일 리스트로 만든 후, for.. yield를 사용할 수 있다.

val names = List("Jax", "Peter", "Tony")
val score = List(100, 80, 90)
val zipped = names.zip(score);

val example = for ((name, score) <- zipped) yield name + "-" + score

println(example);


결과 

List(Jax-100, Peter-80, Tony-90)


zipped는 List((Jax,100), (Peter,80), (Tony,90)) 이다. 






두 리스트의 중복 요소를 찾는 경우에도 사용할 수 있다.

val list1 = List(1, 2, 3)
val list2 = List(7, 9, 1)

val result = for (e1 <- list1 ; e2 <- list2 if e1 == e2) yield e1
print(result)


결과

List(1)












Posted by '김용환'
,