编程语言是无堆栈的到底意味着什么?
根据这个答案
所有这些编程语言都是无堆栈的
- Stackless Python
- PyPy
- Lisp
- Scheme
- Tcl
- Lua
- Parrot VM
对它们来说无堆栈到底意味着什么? 这是否意味着他们不使用调用堆栈? 如果他们不使用调用堆栈,那么他们使用什么?
According to this answer
all of these programming languages are stackless
- Stackless Python
- PyPy
- Lisp
- Scheme
- Tcl
- Lua
- Parrot VM
What does it really mean for them to be stackless? Does it mean they don't use a call stack? If they don't use a call stack, what do they use?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,差不多是这样。
当然,具体的实现因语言而异。 在 Stackless Python 中,有一个调度程序,它使用最顶层的帧及其结果来启动 Python 解释器。 解释器根据需要一次处理一个操作码,直到到达
CALL_FUNCTION
操作码,即您将要进入函数的信号。 这会导致调度程序使用相关信息构建一个新帧,并使用展开标志返回给调度程序。 从那里,调度程序重新开始,将解释器指向最上面的框架。无堆栈语言出于多种原因避开调用堆栈,但在许多情况下,使用它是为了使某些编程结构变得更容易实现。 规范的一个是延续。 延续是非常强大、非常简单的控制结构,可以表示您可能已经熟悉的任何常用控制结构(
while
、do
、if、
switch
等)。如果这令人困惑,您可能想尝试一下维基百科文章,特别是可爱的延续三明治类比:
Yes, that's about right.
The exact implementation will, of course, vary from language to language. In Stackless Python, there's a dispatcher which starts the Python interpreter using the topmost frame and its results. The interpreter processes opcodes as needed one at a time until it reaches a
CALL_FUNCTION
opcode, the signal that you're about to enter into a function. This causes the dispatcher to build a new frame with the relevant information and return to the dispatcher with the unwind flag. From there, the dispatcher begins anew, pointing the interpreter at the topmost frame.Stackless languages eschew call stacks for a number of reasons, but in many cases it's used so that certain programming constructs become much easier to implement. The canonical one is continuations. Continuations are very powerful, very simple control structures that can represent any of the usual control structures you're probably already familiar with (
while
,do
,if
,switch
, et cetera).If that's confusing, you may want to try wrapping your head around the Wikipedia article, and in particular the cutesy continuation sandwich analogy:
它们不使用调用堆栈,因为它们以延续传递风格运行。 如果您不熟悉尾部调用优化,这可能是理解其含义的良好第一步。
为了模拟此模型上的传统调用/返回,调用者不会推送返回地址并期望帧的其余部分保持不变,而是关闭其代码的其余部分以及仍然需要的任何变量(其余部分被释放)。 然后,它对被调用者执行尾调用,将此延续作为参数传递。 当被调用者“返回”时,它通过调用此延续并将返回值作为参数传递给它来实现。
就上述而言,这只是一种执行函数调用的复杂方法。 然而,它可以很好地推广到更复杂的场景:
They don't use a call stack, because they operate in continuation-passing style. If you're not familiar with tail call optimization, that's probably a good first step to understanding what this means.
To emulate the traditional call/return on this model, instead of pushing a return address and expecting the remainder of the frame to remain untouched the caller closes over the remainder of its code and any variables that are still needed (the rest are freed). It then performs a tail call to the callee, passing this continuation as an argument. When the callee "returns", it does so by calling this continuation, passing the return value as an argument to it.
As far as the above goes, it's merely a complicated way to do function calls. However, it generalizes very nicely to more complex scenarios: