为啥要使用面向堆栈的语言? [关闭]
Posted
技术标签:
【中文标题】为啥要使用面向堆栈的语言? [关闭]【英文标题】:Why use a stack-oriented language? [closed]为什么要使用面向堆栈的语言? [关闭] 【发布时间】:2011-08-01 04:36:43 【问题描述】:我最近看了Factor,基于堆栈概念的语言的想法非常有趣。 (这是我第一次遇到面向堆栈的语言。)但是,我没有看到这种范式的任何实际优势。对我来说,这似乎比它的价值更麻烦。为什么要使用 Factor 或 Forth 等面向堆栈的语言?
我忽略了工具和库的可用性等因素(请原谅双关语)。我只问语言范式本身。
【问题讨论】:
一个疯狂的猜测——从语法上看,它可能可以非常有效地编译。也许您可以期望用 Factor 编写的程序非常快。 另一个疯狂的猜测:你看过 golfscript 吗?如果你真的很擅长它,你可以用很少的代码解决问题。 golfscript.com/golfscript @Hamish:也许吧,虽然现在肯定不是这样,但人们仍在使用这些语言。 Postscript(因此也包括 PDF)使用堆栈语言。 一旦你习惯了堆栈,它就会变得很好。例如,您可以在需要前 10 行将某些东西放在堆栈上,等待,然后在没有任何额外变量(需要命名、记录等)的情况下将其取回。 【参考方案1】:[已编辑] 我们已经有了很好的答案,但我对 Factor 语言一无所知。然而,正如所问的那样,支持堆栈使用是面向堆栈范式的一个实际优势,也是采用这种范式的一个理由。
所以,为了完整性,我认为值得列出使用堆栈而不是堆分配的优点:
CPU 时间——在堆栈中分配内存的时间成本实际上是免费的:无论您分配一千个整数还是一千个整数,只需要一个堆栈指针递减操作即可。 example Memory leak -- 仅使用堆栈时没有内存泄漏。这自然会发生,无需额外的代码开销来处理它。即使在异常处理或使用 longjmp(无引用计数、垃圾收集等)从每个函数返回时,函数使用的内存也会完全释放。 Fragmentation -- 堆栈也自然地避免了内存碎片。您可以实现零碎片,而无需任何额外的代码来处理这个问题,比如对象池或平板内存分配。 Locality -- 堆栈中的数据有利于数据局部性,利用缓存并避免页面交换。当然,实现起来可能会更复杂,具体取决于您的问题,但我们将始终支持堆栈而不是堆,我们可以在任何语言中使用。仅在实际需要时(大小或生命周期要求)才使用 malloc/new。
【讨论】:
这些原因与为什么要将堆栈呈现给程序员无关。更主流的、非基于堆栈的语言,如 C,以完全相同的方式实现。 嗯,隐含的想法(我认为这很明显)是:堆栈分配的优点是面向堆栈的范例的实际优势。所以,我相信这是一个互补的答案。换句话说:“问:我没有看到这种范式有任何实际优势。为什么我要使用面向堆栈的语言?” A:因为它会促进堆栈的使用,这是一个实际的优势。【参考方案2】:堆栈方向是一个实现细节。例如,Joy 可以使用重写来实现 - 没有堆栈。这就是为什么有些人更喜欢说“连接”或“组合”。使用引号和组合符,您可以在不考虑堆栈的情况下进行编码。
用纯粹的组合表达自己,没有局部变量或命名参数是关键。它非常简洁,没有语法开销。组合使得排除冗余和“代数”操作代码变得非常容易;将其归结为本质。
一旦你爱上了这种无点风格,你就会对其他语言中最轻微的组合语法(即使只是一个点)感到恼火。在连接语言中,空格是组合运算符。
【讨论】:
Manfred von Thun 的“Joy 的条件项重写系统”论文的“堆栈的作用”部分读起来很有趣! kevinalbrecht.com/code/joy-mirror/j07rrs.html【参考方案3】:开发基于堆栈的语言的一个重要原因是,它们的语义极简主义允许直接的解释器和编译器实现以及优化。
因此,这种范式的实际优势之一是它允许爱好者轻松地在它们之上构建更复杂的事物和范式。
Scheme 编程语言是另一个例子:极简的语法和语义,简单的实现,以及很多乐趣!
【讨论】:
【参考方案4】:我不确定这是否能完全回答您的问题,但您会发现 Factor 首先将自己描述为 concatenative 语言。它恰好也有一个基于堆栈的执行模型。不幸的是,我找不到 Slava 的博文(?或者可能在 Factor Wiki 上?)谈论这个。
串联模型基本上意味着您传递“大量代码”(好吧,无论如何,这就是您的编程方式)并且组合看起来像串联。像柯里化这样的操作也很容易用基于堆栈的语言来表达,因为您只需预先编写向堆栈添加一件事的代码。至少在 Factor 中,这是通过一个名为curry
的词来表达的。这使得进行高阶编程变得更加容易,并且对序列的映射最终成为“显而易见的方法”。我来自 Lisp,在使用 Factor 编程后,我惊讶地发现你无法在 Lisp 中做像 bi
这样的“显而易见的事情”。它确实改变了你表达事物的方式。
顺便说一句,明智的做法是不要过于关注整个堆栈操作。使用locals
词汇表(在此描述:http://docs.factorcode.org/content/article-locals.html),您不必担心乱七八糟的事情。通常有一种不用局部变量的简洁方式来表达事物,但我倾向于第二种方式。
【讨论】:
那么为什么不直接使用函数式语言呢?当然,它更适合于柯里化和高阶编程之类的事情。而且我意识到您可以(并且应该)抽象出 Factor 和其他语言中的堆栈操作内容,但是首先有什么意义呢?不过,感谢您的回答。【参考方案5】:对于某些人来说,管理堆栈比其他范例更容易思考。至少,使用基于堆栈的语言进行一些 hacking 会总体上提高您管理堆栈的能力。
顺便说一句:在手持计算器的早期,他们使用称为Reverse Polish notation 的东西,这是一种非常简单的基于堆栈的后缀表示法,并且非常节省内存。学会有效使用它的人往往更喜欢它而不是代数计算。
【讨论】:
这给您带来的一大好处是您无需担心运算符优先级。没有更多的运算符顺序表,或者实际上是括号。在您习惯这一点之前,您不会真正体会到“普通”代码是多么令人讨厌。以上是关于为啥要使用面向堆栈的语言? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
Google 的 go 语言是不是解决了 Paul 的 Graham 的帖子“为啥 Arc 不是特别面向对象”中的问题?