为什么使用面向堆栈的语言?
我最近看了一下Factor ,关于使用基于堆栈概念的语言的想法非常有趣。 (这是我第一次遇到一个面向堆栈的语言)。但是,我没有看到这样一个范例的实际优势。 对我来说,这看起来更麻烦,而不是值得。 为什么我会使用诸如Factor或Forth之类的面向堆栈的语言?
我无视因素(原谅双关语),如工具和库的可用性。 我只是在问语言范式本身。
堆栈方向是一个实现细节。 例如,Joy可以使用重写来实现 – 不需要堆栈。 这就是为什么有些人喜欢说“连接”或“成分”。 用引号和组合器,你可以不用考虑堆栈而编写代码。
expression自己的纯粹成分,没有当地人或有名的论据是关键。 它非常简洁,没有语法开销。 组合使得容易分解冗余和“代数”操作你的代码; 把它煮到它的本质。
一旦你爱上了这种无点式的风格,即使是其他语言(即使只是一个点),即使是最细微的组合语法也会让你感到恼火。 在连接语言中,空白是组合操作符。
我不确定这是否会回答你的问题,但是你会发现Factor首先将自身描述为一种连接语言。 它恰好也有一个基于堆栈的执行模型。 不幸的是,我找不到Slava的博客文章(或者可能在Factor Wiki上)。
连接模型基本上意味着你传递“代码块”(嗯,这就是你如何编程)和组合看起来像串联。 像柯里化这样的操作也很容易用基于堆栈的语言来expression,因为你只是预先编写代码来添加一些东西到堆栈中。 至less在因素中,这是通过一个叫做curry
的词来expression的。 这使得进行更高级的编程变得更容易,并且对序列的映射最终成为“明显的做法”。 我来自Lisp,在因子编程后感到惊讶,因为你不能在Lisp中做“明显的事情”,比如bi
。 这确实改变了你如何expression的东西。
顺便说一下,明智的做法是不要在整个堆栈操作上挂得太高。 使用locals
词汇(这里描述: http : //docs.factorcode.org/content/article-locals.html ),你不必担心洗牌的事情。 通常有一种很好的方式来expression没有局部variables的东西,但是我倾向于这样做。
正在开发基于堆栈的语言的重要原因之一是因为其语义的极简主义允许直接的解释器和编译器实现以及优化。
所以,这种范式的实际优势之一是它可以让发烧友们轻松地在他们之上build立更复杂的事物和范例。
Scheme编程语言就是另外一个例子:最简单的语法和语义,简单的实现和很多的乐趣!
对于一些人来说,pipe理堆栈比其他范例更容易思考。 至less,使用基于堆栈的语言进行一些黑客攻击可以提高您一般pipe理堆栈的能力。
除此之外:在手持计算器的早期,他们使用了一种称为Reverse Polish notation的方法 ,这是一种非常简单的基于堆栈的后缀表示法,并且具有极高的内存效率。 学习有效使用它的人往往比代数计算更喜欢它。
我们已经有了很好的答案,对于因子语言我一无所知。
但是,我认为这是值得评论的补充:
- CPU时间 – 堆栈中的内存分配的时间成本实际上是免费的:分配一个或一千个整数无关紧要,只需要一个堆栈指针递减。 例
- 内存泄漏 – 仅使用堆栈时没有内存泄漏。 这种情况自然发生,无需额外的代码开销来处理它。 即使在exception处理或使用longjmp(不参考计数,垃圾回收等)时,函数使用的内存在从每个函数返回时都会完全释放。
- 碎片 – 堆栈也避免了内存碎片。 你可以实现零碎片,而不需要任何额外的代码来处理这个对象池或slab内存分配。
- 局部性 – 堆栈支持数据局部性,利用caching并避免页面交换。
当然,实施起来可能会更复杂一些,这取决于你的问题,但是我们应该总是倾向于堆栈堆栈。