복붙노트

[SCALA] 스칼라 연속 요청을 사용하여 수율 (수율 반환)를 구현

SCALA

스칼라 연속 요청을 사용하여 수율 (수율 반환)를 구현

어떻게 스칼라의 연속 요청을 사용하여 C # 수율 반환을 구현할 수 있는가? 나는 같은 스타일 스칼라 반복자를 작성할 수 있도록하고 싶습니다. 자상이 스칼라 뉴스 게시물에 코멘트에이지만 (스칼라 2.8.0 베타를 사용하여 시도) 작동하지 않습니다. 관련 질문에 대한 답변이 가능 제안,하지만 난 잠시 동안 구분 연속성을 가지고 노는 봤는데 있지만, 나는 정확히이 작업을 수행하는 방법을 주위에 내 머리를 정리하고 수없는 것.

해결법

  1. ==============================

    1.우리가 연속성을 소개하기 전에 우리는 몇 가지 인프라를 구축 할 필요가있다. 다음은 반복 객체에 작동하는 트램 폴린이다. 반복 중 하나에 새로운 값을 얻을 수 계산하거나 그 수행 될 수있다.

    우리가 연속성을 소개하기 전에 우리는 몇 가지 인프라를 구축 할 필요가있다. 다음은 반복 객체에 작동하는 트램 폴린이다. 반복 중 하나에 새로운 값을 얻을 수 계산하거나 그 수행 될 수있다.

    sealed trait Iteration[+R]
    case class Yield[+R](result: R, next: () => Iteration[R]) extends Iteration[R]
    case object Done extends Iteration[Nothing]
    
    def trampoline[R](body: => Iteration[R]): Iterator[R] = {
      def loop(thunk: () => Iteration[R]): Stream[R] = {
        thunk.apply match {
          case Yield(result, next) => Stream.cons(result, loop(next))
          case Done => Stream.empty
        }
      }
      loop(() => body).iterator
    }
    

    트램폴린이 반복 시퀀스가 ​​스트림 오브젝트 회전하는 내부 루프를 사용한다. 우리는 그 결과의 스트림 객체에 반복자를 호출하여 반복자를 얻을. 우리의 평가 게으른 스트림을 사용하여; 필요할 때까지 우리는 우리의 다음 반복을 평가하지 않습니다.

    트램 폴린 직접 반복자를 구축하는 데 사용할 수 있습니다.

    val itr1 = trampoline {
      Yield(1, () => Yield(2, () => Yield(3, () => Done)))
    }
    
    for (i <- itr1) { println(i) }
    

    즉 그래서 우리의 반복 객체를 자동으로 생성 할 구분의 연속 요청을 사용하자, 쓰기에 꽤 끔찍한입니다.

    우리는 반복으로 계산을 파괴하기 위해 변화와 리셋 연산자를 사용하여 다음 반복자에 반복을 설정하는 트램 폴린을 사용합니다.

    import scala.continuations._
    import scala.continuations.ControlContext.{shift,reset}
    
    def iterator[R](body: => Unit @cps[Iteration[R],Iteration[R]]): Iterator[R] =
      trampoline {
        reset[Iteration[R],Iteration[R]] { body ; Done }
      }
    
    def yld[R](result: R): Unit @cps[Iteration[R],Iteration[R]] =
      shift((k: Unit => Iteration[R]) => Yield(result, () => k(())))
    

    이제 우리는 우리의 예를 다시 작성할 수 있습니다.

    val itr2 = iterator[Int] {
      yld(1)
      yld(2)
      yld(3)
    }
    
    for (i <- itr2) { println(i) }
    

    훨씬 낫다!

    이제 여기 수율이 쇼 좀 더 고급 사용에 대한 C #을 참조 페이지에서 예입니다. 종류는 사용하기가 까다로운 약간 수 있지만 모든 작품을 할 수 있습니다.

    def power(number: Int, exponent: Int): Iterator[Int] = iterator[Int] {
      def loop(result: Int, counter: Int): Unit @cps[Iteration[Int],Iteration[Int]] = {
        if (counter < exponent) {
          yld(result)
          loop(result * number, counter + 1)
        }
      }
      loop(number, 0)
    }
    
    for (i <- power(2, 8)) { println(i) }
    
  2. ==============================

    2.나는 장난보다 몇 시간 후에이 작업을 수행 할 수있는 방법을 발견 할 수 있었다. 내가 나중에 않았지만 매우 리치의 및 마일의 솔루션을 주셔서 감사합니다, 이것이 내가 지금까지 본 적이 모든 다른 솔루션에 비해 주위에 내 머리를 정리하는 것이 더 간단 생각했다.

    나는 장난보다 몇 시간 후에이 작업을 수행 할 수있는 방법을 발견 할 수 있었다. 내가 나중에 않았지만 매우 리치의 및 마일의 솔루션을 주셔서 감사합니다, 이것이 내가 지금까지 본 적이 모든 다른 솔루션에 비해 주위에 내 머리를 정리하는 것이 더 간단 생각했다.

    def loopWhile(cond: =>Boolean)(body: =>(Unit @suspendable)): Unit @suspendable = {
      if (cond) {
        body
        loopWhile(cond)(body)
      }
    }
    
      class Gen {
        var prodCont: Unit => Unit = { x: Unit => prod }
        var nextVal = 0
        def yld(i: Int) = shift { k: (Unit => Unit) => nextVal = i; prodCont = k }
        def next = { prodCont(); nextVal }
        def prod = {
          reset {
            // following is generator logic; can be refactored out generically
            var i = 0
            i += 1
            yld(i)
            i += 1
            yld(i)
            // scala continuations plugin can't handle while loops, so need own construct
            loopWhile (true) {
              i += 1
              yld(i)
            }
          }
        }
      }
      val it = new Gen
      println(it.next)
      println(it.next)
      println(it.next)
    
  3. from https://stackoverflow.com/questions/2201882/implementing-yield-yield-return-using-scala-continuations by cc-by-sa and MIT license