for 내장(comprehension) (또는 for yield문)에 대한 예시이다.
for 내장은 다중 for 문으로 생각하는 게 좋다.
그리고, yield를 map/flatmap/foreach와 비슷한 느낌으로 보는게 좋은 듯 하다. 따라서 for 내장의 라인은 큰 의미가 있기 때문에 주의해서 쓸 필요가 있다.
즉, 아래와 같은 문장은 쓸 수 없고, 컴파일 에러가 난다.
val m = for {
a = 5
b = 3
} yield (a + b)
에러 내용이다.
Error:(12, 7) '<-' expected but '=' found.
a = 5
Error:(13, 1) illegal start of simple expression
b = 3
아래 코드도 에러가 발생하지만, for 내장에 대해서 조금 이해할 수 있다.
val m = for {
a <- 1
b <- 2
} yield (a + b)
에러 내용이다.
Error:(12, 10) value flatMap is not a member of Int
a <- 1
Error:(13, 10) value map is not a member of Int
b <- 2
다음과 같은 에러가 발생하는데. 첫 번째 라인에서는 flatmap, 다음은 map관련 에러가 발생한다.
즉, for 내장은 내부적으로 변환된다는 의미를 가진다.
마지막 문장은 map이고, 이전 문장은 flatmap으로 변환된다.
동작되는 for 내장 예시를 소개한다.
for {
l <- List(1,2,3,4,5)
} yield l.println
결과는 다음과 같다.
1
2
3
4
5
val m = for {
s <- List("a", "bb", "ccc")
} yield s.length
println(m)
결과는 다음과 같다.
List(1, 2, 3)
그리고 2차 for문처럼 쓸 수 있다.
for {
i <- 1 to 2
j <- 3 to 4
} println(s"$i + $j = ${i + j}")
결과는 다음과 같다.
1 + 3 = 4
1 + 4 = 5
2 + 3 = 5
2 + 4 = 6
object Main extends App {
val m = for {
s <- List("1", "a", "3")
c <- s
} yield s"${s} - ${c}"
println(m)
}
결과는 다음과 같다.
List(1 - 1, a - a, 3 - 3)
val m = for {
s <- List("1", "a", "3")
c <- s
if c.isLetter
} yield s"${s} - ${c}"
println(m)
결과는 다음과 같다.
List(a - a)
yield에 콜렉션(튜플)을 사용할 수 있다.
val m = for {
s <- List("b4", "a", "3")
c <- s
} yield (s, c)
m.foreach(println)
결과는 다음과 같다.
(b4,b)
(b4,4)
(a,a)
(3,3)
option으로 테스트 해본다.
val m = for {
i <- List(1, 2, 3, 0)
} yield (i * 10)
m.foreach(println)
결과는 다음과 같다.
10
20
30
0
Some으로 내용을 감싸면 내부적으로 Some None에 따라 값을 구한다.
val m = for {
Some(i) <- List(Some(1), Some(2), Some(3), None)
} yield (i * 10)
m.foreach(println)
결과는 다음과 같다.
10
20
30
참고로 인스턴스는 사용한 콜렉션을 따르다. 아래 결과는 Vector(10, 20, 30)이다.
val m = for {
Some(i) <- Vector(Some(1), Some(2), Some(3), None)
} yield (i * 10)
println(m)
함수를 사용할 때는 리턴 타입이 Option로 감쌀 때 잘 동작한다. 그냥 하면 에러가 발생한다.
다음은 에러 케이스이다.
def isAllDigits(s: String) : Int = {
if (s forall Character.isDigit) {
return s.toInt
}
0
}
val m = for {
a <- isAllDigits("1")
b <- isAllDigits("2")
c <- isAllDigits("9")
} yield (a + b + c)
println(m)
결과는 다음과 같다.
Error:(33, 21) value flatMap is not a member of Int
a <- isAllDigits("1")
Error:(34, 21) value flatMap is not a member of Int
b <- isAllDigits("2")
Error:(35, 21) value map is not a member of Int
c <- isAllDigits("9")
다음은 Option을 래핑한 예시이다.
def isAllDigits(s: String) : Option[Int] = {
if (s forall Character.isDigit) {
return Some(s.toInt)
}
Some(0)
}
val m = for {
a <- isAllDigits("1")
b <- isAllDigits("2")
c <- isAllDigits("9")
} yield (a + b + c)
println(m)
결과는 다음과 같다.
Some(12)
잘못된 결과가 나와도 잘 동작한다.
def isAllDigits(s: String) : Option[Int] = {
if (s forall Character.isDigit) {
return Some(s.toInt)
}
Some(0)
}
val m = for {
a <- isAllDigits("1")
b <- isAllDigits("a")
c <- isAllDigits("2")
} yield (a + b + c)
println(m)
'scala' 카테고리의 다른 글
[scala] 클래스 초기화하기(생성) (0) | 2016.12.13 |
---|---|
[scala] 부모 클래스를 상속받고 트레이트를 믹스인한 클래스의 생성 순서 (0) | 2016.12.13 |
[scala] try-catch/Try-match/Either/Validation (0) | 2016.12.06 |
[scala] 부분 적용 함수 / 커링 / 부분 함수 (0) | 2016.12.05 |
[scala] 꼬리 재귀(tail recursion)와 @tailrec (0) | 2016.12.05 |