https://docs.scala-lang.org/tutorials/FAQ/yield.html
for {...} yield 는 python의 yield와는 다르다.
python의 yield는 iterator를 만든다.
scala의 yield는 high order function의 syntactic sugar일 뿐이다.
scala는
for (enumerators) yield e
형태를 이용해서 sequence를 표현하는데, 이것을 for comprehension이라 한다.
https://docs.scala-lang.org/tour/for-comprehensions.html
for {...} yield는 이러한 for comprehension 형태로 high order function을 나타낸 것뿐이다.
javascript의 callback 지옥처럼, 여러 개의 high order function을 이용하면,
다음처럼 계속해서 nested되어 코드가 보기 좋지 않다.
l.flatMap(sl => sl.filter(el => el > 0).map(el => el.toString.length))
그래서 위 코드를 for{...} yield를 이용해서 다음처럼 바꿀 수 있다.
for{
sl <- l
el <- sl
if el > 0
} yield el.toString.length
(예시는 scala documenation에서 가져왔습니다.)
실제로 for {...} yield 형태로 작성한 코드는 foreach, map, flatMap, filter, withFilter로 변환된다고 한다.
어떻게 변환되는지 알아보자
1.foreach
for(x <- c1; y <- c2) {...}
c1.foreach(x => c2.foreach(y => c3.foreach(z => {...})))
2.map
for(x <- c; y = ...) yield {...}
c.map(x => (x, ...)).map((x,y) => {...})
y = ... 부분이 없다면, vector가 만들어지는 기본 for {....} yield 가 된다.
생각해보면 당연히 이것은 map function과 동일하다
for(x <- c) yield {...}
c.map(x => (x, ...))
3.flatMap
for(x <- c1; y <- c2) yield {...}
c1.flatMap(x => c2.map(y =>{...}))
4. withFilter / filter
for(x <- c; if cond) yield {...}
withFilter가 정의되어 있으면 withFilter로,
withFilter가 정의되지 않으면 filter로 변환한다.
c.withFilter(x => cond).map(x => {...})
개인적으로 처음 for {...} yield를 사용할 때, high order function으로 변환된다는 것을 제대로 이해하지 못해 고생했다.
단순히 map의 chaining으로 변환된다고 생각해서 막무가내로 코드를 작성했는데, compile조차도 안되고 난리도 아니었다.
error 원인도 다양했다.
{} 안에서 <-가 안되거나, type mismatch, withFilter is not defined.... 등등
처음에는 withFilter is not defined를 보면서, 이게 왜 나오지...? 생각했는데,
high order function의 syntatic sugar라는 것을 알고 나니 이해가 되었다.
물론 그걸 이해했다고 해서 에러를 해결할 수 있는 것은 아니다...@
그리고 무조건적으로 high order function으로 바뀐다고 할 수도 없는 것 같다.
scala documentation에
a syntactic sugar for composition of multiple monadic operations
라고 표현된 것을 보면, 추가적인 의미가 있는 것 같다.
몇 가지 실험한 결과를 정리해서 다른 글에 정리해보려 한다.
그리고 제발, documentation을 잘 읽자.....
'언어 > Scala' 카테고리의 다른 글
Reactive Programming, Functional programming, Reactive Principles (0) | 2020.02.08 |
---|---|
for {...} yield 실험 결과 정리 (0) | 2020.02.03 |
type / class 확인하기 (0) | 2020.01.26 |
for{...} yield 이해하기2 (0) | 2020.01.26 |
for loop/ for() /for{} /for(...) yield (0) | 2020.01.26 |