我很有诱惑力使用未经检查的异常作为Java程序中的短路控制流构造.我希望有人能以更好,更清洁的方式告诉我这个问题.
我的想法是,我希望减少访问者对子树的递归探索,而不必在每个方法调用中检查"停止"标志.具体来说,我正在使用抽象语法树上的访问者构建控制流图.returnAST中的语句应该停止对子树的探索,并将访问者发送回最近的封闭if/then或循环块.
的Visitor超类(从XTC库)定义
Object dispatch(Node n)
Run Code Online (Sandbox Code Playgroud)
通过表单的反射方法回调
Object visitNodeSubtype(Node n)
Run Code Online (Sandbox Code Playgroud)
dispatch 没有声明抛出任何异常,所以我声明了一个扩展的私有类 RuntimeException
private static class ReturnException extends RuntimeException {
}
Run Code Online (Sandbox Code Playgroud)
现在,return语句的visitor方法看起来像
Object visitReturnStatement(Node n) {
// handle return value assignment...
// add flow edge to exit node...
throw new ReturnException();
}
Run Code Online (Sandbox Code Playgroud)
并且每个复合语句都需要处理 ReturnException
Object visitIfElseStatement(Node n) {
Node test = n.getChild(0);
Node ifPart = n.getChild(1);
Node elsePart = n.getChild(2);
// add flow edges to if/else...
try{ dispatch(ifPart); } catch( ReturnException e ) { …Run Code Online (Sandbox Code Playgroud) 我想知道是否有可能定义一个递归函数而不在其体内调用函数本身,但不知何故使用call/cc代替?谢谢.
前言
我试图围绕如何实际使用ContT和callCC有用的东西.我无法跟踪代码周围的信息和控制流程.(但是,这不是延续的意义吗?)
有很多不同的方法可以用这个monad和少量非常直接的组合器来移动碎片.我将承认我对ContT的工作方式的理解仍感到不安,但我会指出我到目前为止所阅读的内容:
我想做的是发布一个psudo-code示例,然后询问一些有关它的问题.这代表使用ContT的典型代码外观
Psudo码
type MyMonad r = ContT r (State SomeState)
main = do
runState s_init $ runContT block print
block :: MyMonad r a0
block = do
before_callcc
output <- callCC $ \k -> do
rval <- inner_block
return rval
after_callcc
Run Code Online (Sandbox Code Playgroud)
问题
output?b这种类型的意思是k什么?k哪里?inner_block运行?它看到的是什么版本的州?rval去了,它的类型是什么?k和之间有什么关系rval? …在Clojure的core.async库中,我们看到一个宏,它创建一个状态机,它围绕go块来创建处理阻塞IO的通道.
这似乎是在 C#async 和 Go-lang的goroutines 上进行建模.
在The Seasoned Schemer中 - 他们描述了传递延续的技巧.(这似乎是基于电话/ cc).我们还看到了David Nolen的一个图书馆在Clojure 上的分隔延续.
在这里,他们将C#描述async为" 当前延续的呼叫 ".
我的问题是我们可以将Clojure的core.async描述为" 延续传递风格 "吗?
或者是'延续'(分隔和无限制)一个超载的术语?
编辑:另外一点 - 大卫·诺伦已经说过核心.async:
在一个go块中,它给你一种错觉,你可以以同步的方式做这些事情,这样你就不必手动以连续传递方式编写代码.
Ruby callcc捕获当前的延续,随后可以调用它来恢复控件,但不能恢复数据.我想捕获当前的延续以及当前的内存图像.
在我看来,抓住堆应该不是很困难; 我可以依靠ObjectSpace::each_object和ObjectSpace::dump_all,或Marshal.dump,或简单地Object.clone.但是,我没有看到任何简单的方法来恢复堆.理想情况下,我想遍历object_id -> object 地图,为每个地图恢复对象的旧图像object_id(object_id如果相应的对象已经过GC ,则重新添加).不出所料,没有Ruby级别的api可以让我这样做.我想知道是否有任何我可以使用的Ruby GC的低级钩子.
任何帮助表示赞赏,包括有关替代方法的建议.
这与什么是电话/ cc有关?但是我不想为了我自己的目的而劫持这个问题,而且它的一些论据就像对setjmp/longjmp的类比一样逃避了我.
我认为我对延续是什么有足够的了解,我认为它是当前调用堆栈的快照.我不想讨论为什么这可能有趣或者你可以用延续做什么.我的问题更具体地说,为什么我必须提供一个函数参数来调用/ cc?为什么不调用/ cc只返回当前的延续,所以我可以用它做任何事情(存储它,调用它,你命名它)?在另一个问题(http://community.schemewiki.org/?call-with-current-continuation-for-C-programmers)的链接中,它谈到"基本上它只是一种干净的方式来延续你并且不要让后续跳回到保存的点.",但我没有得到它.这似乎不必要地复杂化.
我需要了解我即将进行的考试中的Continuations in Scheme,我根本不知道延续.任何人都可以建议我如何继续学习延续的来源?
问候,
darkie
考虑函数的Haskell中的以下示例quux以及continuation monad和的定义callCC.
instance Monad (Cont r) where
return x = cont ($ x)
s >>= f = cont $ \c -> runCont s $ \x -> runCont (f x) c
callCC :: ((a -> Cont r b) -> Cont r a) -> Cont r a
callCC f = cont $ \h -> runCont (f (\a -> cont $ \_ -> h a)) h
quux :: Cont r Int
quux = callCC $ \k -> do
let …Run Code Online (Sandbox Code Playgroud) 直觉逻辑是建设性的,是函数式编程中类型系统的基础.经典逻辑不是建设性的,特别是被排除的中间A∨¬A(或其等价物,例如双重否定消除或皮尔斯定律)的定律.
但是,我们可以实现(构造)call-with-current-continuation运算符(AKA call/cc),例如在Scheme中.那么为什么不打电话/ cc建设性?
有没有人有一个很好的指导它是如何工作的?带有视觉辅助工具的东西会很好,我遇到的每一个指南似乎都说同样的东西,我需要一个新的东西.
callcc ×10
scheme ×4
haskell ×2
call ×1
clojure ×1
continuation ×1
core.async ×1
curry-howard ×1
exception ×1
goroutine ×1
java ×1
ruby ×1
visitor ×1