假设,我有以下代码(类似 C 的语法):
void foo(int arg) { ... }
内部酒吧(){
...
// 继续调用
...
}
foo ( bar() )
// 在 foo 调用之后
1) 函数foo调用 function bar,该函数一直运行直到到达带有 的行call with continuation。
2) 在这一行continuation创建了一个函数。它代表的休息bar和foo。该continuation函数作为参数传递给call with continuation函数。
3)call with continuation函数对参数做任何它想做的事情(例如,它可能只存储在一个全局变量中)并返回。
4) 一旦call with continuation返回,我们立即跳转到带有“after foo invocation”的那一行,其余的bar和foo不执行。
5)为了继续执行bar,并foo应明确地调用continuation函数(在(2创建),可能存储在(3))。一旦continuation调用该函数,则在 之后立即继续执行call with continuation。 …
language-agnostic continuations programming-languages functional-programming
我认为我得到了一个延续(一般),但我无法理解它是如何在Scheme中使用的.
考虑这个例子(来自wikipedia call/cc)
(define (f return)
(return 2)
3)
(display (call/cc f)) ;=> 2
Run Code Online (Sandbox Code Playgroud)
我不明白为什么:
延续是隐含的吗?对吗?
在这种情况下如何继续?
在Scheme中执行从call/cc有效跳转到初始调用/ cc 获得的延续并恢复保存的调用堆栈.
我刚刚开始学习Haskell,我正在试图弄清楚如何理解callCC.这是试图callCC理解Scheme的理解call/cc.执行callCC是
callCC f = cont $ \h -> runCont (f (\a -> cont $ \_ -> h a)) h
Run Code Online (Sandbox Code Playgroud)
据我所知,没有提到有关保存或恢复调用堆栈的内容.callCCHaskell的解释是如何熟悉Scheme的call/cc.
编辑:也许如果有人可以将以下内容翻译成Haskell,这将有助于我理解.
(define (f return)
(return 2)
3)
(display (f (lambda (x) x))) ; displays 3
(display (call-with-current-continuation f)) ; displays 2
Run Code Online (Sandbox Code Playgroud) 我有以下类型:
data S req rsp = Done rsp | Next req (rsp -> S req rsp)
Run Code Online (Sandbox Code Playgroud)
我们的想法是将其用作网络通信的纯粹表示,即:
... Next GetUser $ \uid -> Next (Login uid) $ \success -> Done success
Run Code Online (Sandbox Code Playgroud)
然后由一些不纯的函数评估eval.
现在,这是什么(如果有的话?)就我所见,这不是一个单子,也不是一个箭头.它似乎是stream/pipe/automaton/fsm和continuation monad之间的东西.这让我觉得这种类型的东西可能有更好的代表性,但是什么呢?
背景
\n\n在确信C++ 无堆栈协程非常棒之后。我一直在为我的代码库实现协程,并意识到 Final_Suspend 中的一个奇怪之处。
\n\n语境
\n\n让\xe2\x80\x99s 假设你有以下final_suspend函数:
\n\nfinal_awaitable final_suspend() noexcept\n{\n return {};\n}\nRun Code Online (Sandbox Code Playgroud)\n\n并且,final_awaitable的实现如下:
\n\nstruct final_awaitable\n{\n bool await_ready() const noexcept\n {\n return false;\n }\n default_handle_t await_suspend( promise_handle_t h ) const noexcept\n { \n return h.promise().continuation();\n }\n void await_resume() const noexcept {}\n};\nRun Code Online (Sandbox Code Playgroud)\n\n如果这里的延续是从任务队列中原子检索的,并且任务队列可能为空(这可能发生在await_ready和await_suspend之间的任何时间),那么await_suspend必须能够返回一个空白延续。
\n\n据我了解,当await_suspend返回句柄时,返回的句柄立即恢复(N4775草案中的5.1)。因此,如果此处没有可用的延续,则任何应用程序都会崩溃,因为在从wait_suspend接收到无效的协程句柄后,会在无效的协程句柄上调用恢复。
\n\n以下是执行顺序:
\n\nfinal_suspend Constructs final_awaitable.\n final_awaitable::await_ready Returns false, …Run Code Online (Sandbox Code Playgroud) 异步方法在调用者上下文/线程上运行同步,直到其执行路径遇到 I/O 或涉及一些等待的类似任务,然后它不等待,而是返回到原始调用者,稍后恢复其继续。问题是,实现“等待”方法的首选方式是什么。文件/网络/等异步方法是如何做到的?
假设我有一个方法,其中涉及一些等待,当前开箱即用的 IO 未涵盖这些等待。我不想阻止调用线程,也不想强迫我的调用者执行 a 来Task.Run()卸载我,我想要一个干净的异步/等待模式,以便我的调用者可以无缝集成我的库,并且我可以在其上下文上运行,直到这样我需要屈服的时候了。为了便于论证,让我们假设我想要创建一个未涵盖的新 IO 库,并且我需要一种方法来使所有保持异步的粘合在一起。
我Task.Yield还要继续吗?我必须自己做Task.Run/Task.Wait等吗?两者看起来更像是相同的抽象(这带来了如何收益的问题Yield)。我很好奇,因为有很多关于 async/await 延续如何为消费者工作以及所有 IO 库如何准备就绪的讨论,但很少有人谈论实际的“突破”点如何工作以及流程制造商应如何实现它。同步路径末尾的代码如何实际释放控制以及该方法在该点和之后如何运行。
如何在Squeak中获得BlockClosure(我想使用BlockClosure >> callCC)?
当我写[#foo]这是一个BlockContext时,这是什么交易?
更新:我已经知道BlockClosure主要是新编译器.
相反,我如何使用海边Continuations?我遇到了问题,任何例子都会受到赞赏.
进一步更新:这样做的目的不是使用海边(至少不是直接),而是以比滚动我自己的状态跟踪迭代器更容易的方式编写遍历和其他类似的东西.
我需要一个真正的迭代器,它将像这样工作:
var haystackObj = {
'needle': 'abc',
'prop2': {
'prop1': 'def',
'prop2': {
'needle': 'ghi',
},
'needle': 'jkl',
},
};
var needleKey = 'needle';
var iterator = {
next: function () {
/*
* WHAT CODE GOES HERE?
*
* Should return the next property, recursively, with the name
* equal to needleKey, of haystackObj.
*
*/
}
};
var value = iterator.next();
console.log(value); // -> 'abc'
value = iterator.next();
console.log(value); // -> 'ghi'
value = iterator.next();
console.log(value); …Run Code Online (Sandbox Code Playgroud) 我很难转换简单的CPS功能
这是CPS风格的方形功能
-- from : http://en.wikibooks.org/wiki/Haskell/Continuation_passing_style
square :: Int -> Int
square x = x * x
square_cps :: Int -> ((Int -> r) -> r)
square_cps = \cont -> cont (square x)
-- square_cps 3 print will write '9' out in console
Run Code Online (Sandbox Code Playgroud)
现在,我想以相反的顺序更改函数参数
square_cps' :: ((Int -> r) -> r) -> Int
square_cps' = ?
Run Code Online (Sandbox Code Playgroud)
这不可能吗?
如何创建使用State,Cont和Reader变换器的monad?我想阅读一个环境,并更新/使用状态.但是,我还想暂停/中断动作.例如,如果满足条件,则状态保持不变.
到目前为止,我有一个使用ReaderT和StateT的monad,但我无法弄清楚如何包含ContT:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Test where
-- monads
import Data.Functor.Identity (Identity, runIdentity)
import Control.Monad.State
import Control.Monad.Reader
import Control.Monad.Cont
-- reader environment
type In = Integer
-- cont: if true then pause, else continue
type Pause = Bool
-- state environment:
newtype StateType = StateType { s :: Integer }
newtype M r = M {_unM :: ReaderT In (ContT Pause (StateT StateType Identity)) r}
deriving ( Functor, Applicative, Monad
, MonadReader In
, MonadCont Pause
, MonadState …Run Code Online (Sandbox Code Playgroud) continuations ×10
haskell ×4
callcc ×2
monads ×2
scheme ×2
arrows ×1
async-await ×1
c# ×1
c++ ×1
c++20 ×1
javascript ×1
seaside ×1
smalltalk ×1
squeak ×1
task ×1