我的背景是 Javascript、Python 和一点 Haskell。我正在尝试理解 callCC,有很多解释,但我找不到它们微不足道的 & 我遇到了这个https://www.cs.bham.ac.uk/~hxt/research/Logiccolumn8.pdf我觉得我几乎明白了,但我需要一些帮助来理解 C 代码。
下面是在 GNU C 中跳回函数的代码。
void *label_as_result() {
return &&L;
L: printf("Jumped back into the function. \n");
}
main () {
void *p;
p = label_as_result();
printf("The function returned; now jump back into it.\n");
goto *p;
}
label_as_result函数中的 return 语句有什么作用?p in main是否将堆栈帧存储在堆中以及它停止的指令行中?跳回函数意味着再次创建一个堆栈帧并从我们离开的地方继续?
在这段代码下面有一段
但是在具有一流函数和callCC的语言中,没有这样的实现限制。就像C中的结果标签一样,我们可以从函数返回由callCC引入的延续,以便跳回函数。当我们使用goto执行此操作时,堆栈被粉碎,但使用 callCC 函数再次返回。考虑以下函数
λ(). callCC(λk. λx. throw k (λy. x))
延续 k 作为结果的一部分返回,大致类似于在 C 中返回标签作为结果。
堆栈被砸了是什么意思,他的意思是如果你使用 goto 会发生堆栈溢出?callCC 如何使用蹦床解决这个问题?
正如许多人所说,callCC 提供了早期返回语义,这意味着它像 python 或 Javascript 中的 yield 吗?是否可以使用yield在Javascript中编写callCC?
我如何在 Javascript 中构思上述代码
function* label_as_result() {
yield () => console.log("Jumped back into the function.");
}
p = label_as_result().next().value;
console.log("The function returned; now jump back into it.");
p();
它甚至可以在没有任何生成器概念的情况下简单地编写为
function label_as_result() {
return () => console.log("Jumped back into the function.");
}
p = label_as_result();
console.log("The function returned; now jump back into it.");
p();
这意味着 callCC 是一个返回延续但所有其他函数都采用延续的函数。延续就像未定的代码,需要在未来执行,而 callCC 就像预定义的代码,需要在未来执行?(我说的是框架和用户代码)