我最近看了Factor,基于堆栈概念的语言的想法非常有趣。(这是我第一次遇到面向堆栈的语言。)但是,我没有看到这种范式的任何实际优势。对我来说,这似乎比它的价值更麻烦。为什么我要使用面向堆栈的语言,例如 Factor 或 Forth?
我忽略了工具和库的可用性等因素(请原谅双关语)。我只问语言范式本身。
我最近看了Factor,基于堆栈概念的语言的想法非常有趣。(这是我第一次遇到面向堆栈的语言。)但是,我没有看到这种范式的任何实际优势。对我来说,这似乎比它的价值更麻烦。为什么我要使用面向堆栈的语言,例如 Factor 或 Forth?
我忽略了工具和库的可用性等因素(请原谅双关语)。我只问语言范式本身。
堆栈方向是一个实现细节。例如,Joy 可以使用重写来实现 - 没有堆栈。这就是为什么有些人更喜欢说“连接”或“组合”。使用引号和组合符,您可以在不考虑堆栈的情况下进行编码。
用纯粹的组合表达自己,没有局部变量或命名参数是关键。它非常简洁,没有语法开销。组合使得排除冗余和“代数”操作代码变得非常容易;将其煮沸至其本质。
一旦你爱上了这种无点风格,你就会对其他语言中最轻微的组合语法(即使只是一个点)感到恼火。在连接语言中,空格是组合运算符。
我不确定这是否能完全回答您的问题,但您会发现 Factor 首先将自己描述为一种连接语言。它恰好也有一个基于堆栈的执行模型。不幸的是,我找不到 Slava 的博文(?或者可能在 Factor Wiki 上?)谈论这个。
串联模型基本上意味着您传递“大量代码”(好吧,这就是您编程的方式)并且组合看起来像串联。像柯里化这样的操作也很容易用基于堆栈的语言来表达,因为您只需预先编写向堆栈添加一件事的代码。至少在 Factor 中,这是通过一个叫做 的词来表达的curry
。这使得进行高阶编程变得更加容易,并且对序列的映射最终成为“显而易见的方式”。我来自 Lisp,并且惊讶地发现在 Factor 中编程了一段时间后,你无法像bi
在 Lisp 中那样做“显而易见的事情”。它确实改变了你表达事物的方式。
顺便说一句,明智的做法是不要过于关注整个堆栈操作。使用locals
词汇表(在此处描述:http: //docs.factorcode.org/content/article-locals.html),您不必担心乱七八糟的事情。通常有一种简洁的方式来表达没有局部变量的东西,但我倾向于这样做。
开发基于堆栈的语言的重要原因之一是因为其语义的极简主义允许直接的解释器和编译器实现以及优化。
因此,这种范式的实际优势之一是它允许爱好者轻松地在它们之上构建更复杂的事物和范式。
Scheme 编程语言是另一个例子:极简的语法和语义,简单的实现,以及很多乐趣!
[已编辑] 我们已经有了很好的答案,但我对 Factor 语言一无所知。然而,正如所问的,支持堆栈使用是面向堆栈范式的一个实际优势,也是采用这种范式的一个原因。
因此,为了完整性,我认为值得列出使用堆栈而不是堆分配的优点:
当然,实现起来可能更复杂,具体取决于您的问题,但我们将始终支持堆栈而不是堆,我们可以在任何语言中使用。仅在实际需要(大小或生命周期要求)时才使用 malloc/new。
对于某些人来说,管理堆栈比其他范式更容易思考。至少,使用基于堆栈的语言进行一些黑客攻击会提高您管理堆栈的能力。
顺便说一句:在手持计算器的早期,他们使用了一种叫做逆波兰表示法的东西,这是一种非常简单的基于堆栈的后缀表示法,并且非常节省内存。学习有效地使用它的人往往更喜欢它而不是代数计算。