我一直在浏览整个网络,寻找关于延续的启示,并且令人难以置信的是,最简单的解释如何能够如此完全混淆像我这样的JavaScript程序员.当大多数文章使用Scheme中的代码解释延续或使用monad时尤其如此.
现在我终于认为我已经理解了延续的本质,我想知道我所知道的是否真的是事实.如果我认为真实的事实并非如此,那么它就是无知而不是启蒙.
所以,这就是我所知道的:
在几乎所有语言中,函数显式地将值(和控制)返回给它们的调用者.例如:
var sum = add(2, 3);
console.log(sum);
function add(x, y) {
return x + y;
}Run Code Online (Sandbox Code Playgroud)
现在,在具有第一类函数的语言中,我们可以将控制和返回值传递给回调,而不是显式返回给调用者:
add(2, 3, function (sum) {
console.log(sum);
});
function add(x, y, cont) {
cont(x + y);
}Run Code Online (Sandbox Code Playgroud)
因此,不是从函数返回值,而是继续使用另一个函数.因此,这个函数被称为第一个的延续.
那么延续和回调之间的区别是什么?
我正在阅读有关列表操作的一些技巧,其中包含以下内容:
Run Code Online (Sandbox Code Playgroud)zipRev xs ys = foldr f id xs snd (ys,[]) where f x k c = k (\((y:ys),r) -> c (ys,(x,y):r))我们在这里可以看到,我们有两个连续的叠放在一起。发生这种情况时,他们通常可以“取消”,如下所示:
Run Code Online (Sandbox Code Playgroud)zipRev xs ys = snd (foldr f (ys,[]) xs) where f x (y:ys,r) = (ys,(x,y):r)
我不明白您如何“取消”堆叠的延续以从顶部的代码块到达底部的代码块。您寻找进行这种转换的方式是什么,为什么会起作用?
连续传递样式(cps)和monad之间有什么区别.
我一直在关注asyncc#5.0中新功能的新公告.我对继续传递样式以及新的c#编译器对Eric Lippert的帖子中的代码片段所做的转换有基本的了解:
async void ArchiveDocuments(List<Url> urls)
{
Task archive = null;
for(int i = 0; i < urls.Count; ++i)
{
var document = await FetchAsync(urls[i]);
if (archive != null)
await archive;
archive = ArchiveAsync(document);
}
}
Run Code Online (Sandbox Code Playgroud)
我知道有些语言通过call-with-current-continuation(callcc)本地实现continuation ,但我真的不明白它是如何工作的或它究竟是做什么的.
所以这就是问题:如果安德斯等人.已经决定咬紧牙关,只是callcc在c#5.0而不是async/ await特殊情况下实现,上面的代码片段会是什么样子?
我一直在学习延续传递样式,特别是在javascript中实现的异步版本,其中一个函数将另一个函数作为最终参数并创建一个异步调用,将返回值传递给第二个函数.
但是,我不能完全看到延续传递除了重新创建管道(如在unix命令行管道中)或流之外还有什么作用:
replace('somestring','somepattern', filter(str, console.log));
Run Code Online (Sandbox Code Playgroud)
VS
echo 'somestring' | replace 'somepattern' | filter | console.log
Run Code Online (Sandbox Code Playgroud)
除了管道更多,更清洁.使用管道,很明显数据被传递,同时执行被传递给接收程序.事实上,对于管道,我希望数据流能够继续向下传递管道,而在CPS中我期望一个串行过程.
或许可以想象,如果通信对象和更新方法与数据一起传递,CPS可以扩展到连续管道,而不是完整的切换和返回.
我错过了什么吗?CPS在某些重要方面有所不同(更好吗?)?
要清楚,我的意思是继续传递,其中一个函数将执行传递给另一个函数,而不仅仅是普通的回调.CPS似乎暗示将函数的返回值传递给另一个函数,然后退出.
假设我们有一个单子,通过定义return,(>>=)以及一套法律.有一种数据类型
newtype C m a = C { unC ? forall r. (a ? m r) ? m r }
Run Code Online (Sandbox Code Playgroud)
也称为密度.C m a ? m a鉴于这m是一个Monad,即我们可以编写两个函数to ? Monad m ? m a ? C m a和from ? Monad m ? C m a ? m a
to ? Monad m ? m a ? C m a
to t = C $ \f ? t …Run Code Online (Sandbox Code Playgroud) 我们可以将continuation monad变换器定义为
data Cont r m a = Cont {run :: (a -> m r) -> m r}
Run Code Online (Sandbox Code Playgroud)
Cont r m如果m是Alternativevia 的成员,我们可以给出Alternative实例
empty = Cont $ \f -> empty
ca <|> cb = Cont $ \f -> run ca f <|> run cb f
Run Code Online (Sandbox Code Playgroud)
然后允许some并many采用他们的默认方法.我的问题是,我们可以定义some并many在以下方面m的some和many,而不是默认的定义是什么?显而易见的选择
some ca = Cont $ \f -> some $ run ca f
many ca = Cont …Run Code Online (Sandbox Code Playgroud) continuations haskell typeclass applicative continuation-passing
有问题的代码是这样的:
(define multirember&co
(lambda (a lat col)
(cond
((null? lat)
(col (quote ()) (quote ())))
((eq? (car lat) a)
(multirember&co a
(cdr lat)
(lambda (newlat seen)
(col newlat
(cons (car lat) seen)))))
(else
(multirember&co a
(cdr lat)
(lambda (newlat seen)
(col (cons (car lat) newlat)
seen))))))
Run Code Online (Sandbox Code Playgroud)
我整天都在盯着这个,但我似乎无法理解它.当您重复使用要重新定义的函数时,col但在示例中它们似乎使用了原始定义.为什么不改变呢.你怎么能在它不复发传递的参数newlat和seen.
很难解释我的问题,因为我似乎只是错过了一块.如果有人能比书更明确地介绍一下,我可能会理解它是如何运作的.
recursion lambda scheme the-little-schemer continuation-passing
我很难理解evens-only*&co第145页的The Little Schemer的例子.
这是代码:
(define evens-only*&co
(lambda (l col)
(cond
((null? l)
(col '() 1 0))
((atom? (car l))
(cond
((even? (car l))
(evens-only*&co (cdr l)
(lambda (newl product sum)
(col (cons (car l) newl)
(opx (car l) product)
sum))))
(else
(evens-only*&co (cdr l)
(lambda (newl product sum)
(col newl product (op+ (car l) sum)))))))
(else
(evens-only*&co (car l)
(lambda (newl product sum)
(evens-only*&co (cdr l)
(lambda (dnewl dproduct dsum)
(col (cons newl dnewl)
(opx product dproduct)
(op+ …Run Code Online (Sandbox Code Playgroud) recursion lambda scheme the-little-schemer continuation-passing
haskell ×3
scheme ×3
callcc ×2
javascript ×2
lambda ×2
recursion ×2
applicative ×1
async-await ×1
asynchronous ×1
c# ×1
fold ×1
monads ×1
pipe ×1
typeclass ×1