跟连乐一起学Scala-定界延续

捕获并执行延续

var count: (Unit => Unit) = null
var fileName = "myfile.txt"
var contents = ""

reset {
    while(contents == "") {
        try {
            contents = scala.io.Source.fromFile(fileName, "UTF-8").mkString
        } catch {case _ => }
        shift {k: (Unit => Unit) =>
                cont = k
        }
    }
}

“运算当中挖个洞”

要理解到底一个延续捕获了什么,我们可以把shift块想象成一个位于reset块中的“洞”。当你执行延续时,你可以将一个值传到这个洞中,运算继续,就好像shift本就是那个值一样。


reset和shift的控制流转

reset/shift的控制流转悠双重职责:一方面定义延续函数,另一方面又捕获延续函数。

当你调用reset时,它的代码体便开始执行。当执行遇到shift时,shift的代码体被调用,传入延续函数作为参数。当shift完成后,执行立即跳转到包含延续的reset块的末尾。

var cont : (Unit => Unit) = null
reset {
    print("Before shift")
    shift {
        k: (Unit => Unit) => {
                cont = k
                println("Inside shift") //跳转到reset末尾
            }
        }
    println("After shift")
    }
    println("After reset")
    cont()

CPS注解

定义:延续传递风格:(CPS)

def tryRead(): Unit @cps[Unit] = {
    while (contents == "") {
        try{
        contents = scala.io.Source.fromFile(filename, "UTF-8").mkString
        }catch {case _ => }
        shift {
            k:(Unit => Unit) =>
            cont = k
        }
    }
}

将递归访问转化为迭代

import scala.util.continuations._
import java.io_

object PrintFiles extends APP {
    var cont : (Unit => Unit) =null

    def processDirectory(dir: File): Unit @cps[Unit] ={
        var files = dir.listFiles
        var i = 0
        while(i < files.length) {
        val f = files(i)
        i += 1
        if (f.isDirectory)
            processDirectory(f)
        else {
            shift {
                k: (Unit => Unit) => {cont = k}
                }//
                println(f)
            }
        }
    }

    reset {
        processDirectory(new File("/"))
    }
    for (i <- 1 to 100) cont()
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值