23장 for expressions revisited - codeport/scala GitHub Wiki

23.1 For expressions

  • for문 형식 (seq : generator, definition, filter의 나열)

      for ( seq ) yield expr
    
    for (p <- persons; n = p.name; if (n startsWith "To"))
    yield n
  • generator의 형식(expr은 보통 리스트를 리턴한다. pat은 패턴으로 리스트에 하나씩 대응된다.)

      pat <- expr
    
  • definition의 형식 (패턴 pat에 expr의 값이 바인드된다.)

      pat = expr
    
  • filter의 형식 (expr은 Boolean타입의 표현식으로 expr이 false인 모든 아이템은 버린다.)

      if expr
    

##23.2 The n-queens problem

##23.3 Querying with for expressions

  • for문을 쿼리문처럼 사용할 수 있다.

##23.4 Translation of for expressions

  • for문은 higher-order 함수인 map, flatmap, withFilter로 변환할 수 있다.

      for ( x <- expr1) yield expr2
      expr1.map(x => expr2)
    
    for (x <- expr1 if expr2) yield expr3
    for (x <- expr1 withFilter (x => expr2)) yield expr3
    expr1 withFilter (x => expr2) map (x => expr3)
    for ( x <- expr1; y <- expr2; seq) yield expr3
    // seq는 generator, definition, filter의 나열
    expr1.flatMap(x => for (y <- expr2; seq) yield expr3)
    for ((x1, ..., xn) <- expr1) yield expr2
    expr1.map { case (x1, ..., xn) => expr2 }
    for (pat <- expr1) yield expr2)
    expr1 withFilter {
        case pat => true
        case _ => false
    } map {
        case pat => expr2
    }
    for (x <- expr1; y = expr2; seq) yield expr3
    for ((x, y) <- for (x <- expr1) yield (x, expr2); seq) yield expr3
    for (x <- expr1) body
    expr1 foreach (x => body)
    for (x <- expr1; if expr2; y <- expr3) body
    expr1 eithFilter (x => expr2) foreach (x => expr3 foreach (y => body))

##23.5 Going the other way

##23.6 Generalizing for

  • 직접 정의한 타입도 필요한 메서드를 구현하면 for문을 완전히 지원할 수 있다.

  • 규칙

      - 타입이 그냥 map을 정의하면 단일 제너레이터르 구성된 for문이 가능하다.
      - 타입이 map과 flatMap을 정의하면 여러 제너레티어구 구성한 for문이 가능하다.
      - 타입이 foreach를 정의하면 for 루프를 사요할 수 있다.(하나이상의 제너레이터로)
      - 타입이 withFilter를 정의하면 for문에 if로 시작하는 필터를 사용할 수 있다.
    
  • for문의 변환은 타입체킹 이전에 일어나므로 아주 유연한 구조가 된다. 왜냐하면 for문 타입케트를 확장한 결과만 필요하기 때문이다. Scala는 for문에 어떤 타입규칙도 없고 map, flatMap, withFilter, foreach가 어떤 시그치너를 가지도록 강제하지 않는다.

  • flatMap
    • map의 수행 결과가 List인 경우 List 해체 작업을 수행해줌

    • 다중 for 문

        for ( x <- List(1,2,3,4,5); y<- List('a','b','c','d','e')) { 
        	(x,y) 
        }
      
    • map, flatMap, filter 버젼으로 변경하는 예제

        scala> List(1,2,3,4,5)
        res1: List[Int] = List(1, 2, 3, 4, 5)
      
        scala> List('a','b','c','d','e')
        res2: List[Char] = List(a, b, c, d, e)
      
        scala> res1.flatMap( x => res2.map( y=> (x,y)) )
        res3: List[(Int, Char)] = List((1,a), (1,b), (1,c), (1,d), (1,e), (2,a), (2,b), (2,c), (2,d), (2,e), (3,a), (3,b), (3,c), (3,d), (3,e), (4,a), (4,b), (4,c), (4,d), (4,e), (5,a), (5,b), (5,c), (5,d), (5,e))