为什么要使用面向堆栈的语言? [关闭]

问题描述 投票:42回答:5

我最近看了一下Factor,并且有一种基于堆栈概念的语言的想法非常有趣。 (这是我第一次遇到面向堆栈的语言。)但是,我没有看到这种范式的任何实际优势。对我来说,它似乎比它的价值更麻烦。为什么我会使用像Stack或Forth这样的面向堆栈的语言?


我忽略了因素(借口双关语),例如工具和库的可用性。我只询问语言范式本身。

stack factor-lang
5个回答
30
投票

堆栈方向是一个实现细节。例如,Joy可以使用重写来实现 - 没有堆栈。这就是为什么有些人喜欢说“串联”或“组合”。使用引号和组合器,您可以在不考虑堆栈的情况下进行编码。

用纯粹的构图表达自己,没有本地人或命名参数是关键。它非常简洁,没有句法开销。组合使得很容易分解冗余并“代数”地操纵你的代码;把它归结为它的本质。

一旦你爱上了这种无点的风格,你就会被其他语言中最轻微的构图语法所困扰(即使只是一个点)。在连接语言中,空格是组合运算符。


10
投票

我不确定这是否能完全回答你的问题,但你会发现因素首先将自己描述为concatenative语言。它恰好也有一个基于堆栈的执行模型。不幸的是,我找不到Slava的博客文章(?或者也许是在因子维基?上)。

连接模型基本上意味着你传递“代码的深刻”(好吧,这就是你的编程方式)和组合看起来像连接。像currying这样的操作也很容易用基于堆栈的语言表达,因为你只是预先编写了一个向堆栈添加一个东西的代码。至少在因子中,这是通过一个名为curry的词来表达的。这使得更高阶的编程变得更容易,并且序列上的映射最终成为“明显的方法”。我来自Lisp并且在使用Factor编程之后回过头来感​​到非常惊讶,因为你不能像Lisp中的bi那样做“明显的事情”。它确实改变了你表达事物的方式。

顺便说一句,明智的做法就是不要在整个堆栈操作上过于笼罩。使用locals词汇表(在此描述:http://docs.factorcode.org/content/article-locals.html),你不必担心随意乱扔东西。通常有一种简洁的方式来表达没有局部变量的东西,但我倾向于那样做。


7
投票

正在开发基于堆栈的语言的一个重要原因是因为它们的语义的极简主义允许直接的解释器和编译器实现,以及优化。

因此,这种范例的一个实际优点是,它允许发烧友们轻松地在他们之上构建更复杂的事物和范例。

Scheme编程语言就是另一个例子:极简主义的语法和语义,简单的实现,以及很多乐趣!


4
投票

[编辑]我们已经有了很好的答案,我对因子语言一无所知。然而,正如所要求的那样,有利于堆栈使用是面向堆栈的范例的实际优势以及采用这种范例的理由。

因此,我认为值得列出堆栈使用的优势而不是堆分配的完整性:

  • CPU时间 - 堆栈中内存分配的时间成本几乎是免费的:如果要分配一个或一千个整数并不重要,它只需要一个堆栈指针递减操作。 example
  • Memory leak - 仅使用堆栈时没有内存泄漏。这种情况自然发生,无需额外的代码开销来处理它。当从每个函数返回时,即使在异常处理或使用longjmp(没有引用计数,垃圾收集等)时,函数使用的内存也会完全释放。
  • Fragmentation - Stacks也可以自然地避免内存碎片。您可以实现零碎片,而无需任何其他代码来处理此对象,如对象池或slab内存分配。
  • Locality - 堆栈中的数据有利于数据本地,利用缓存和避免页面交换。

当然,根据你的问题,实现它可能会更复杂,但我们总是倾向于使用堆栈而不是任何语言。保留malloc / new仅在实际需要时使用(大小或生命周期要求)。


3
投票

对于某些人来说,在管理堆栈方面比其他范例更容易思考。至少,在基于堆栈的语言中进行一些黑客操作将提高您管理堆栈的能力。

除此之外:在手持式计算器的早期,他们使用了一种名为Reverse Polish notation的东西,这是一种非常简单的基于堆栈的后缀符号,并且具有极高的内存效率。学会有效使用它的人往往更喜欢它而不是代数计算。


2
投票

Research / Development / Understanding Popular Virtual Machines

JVM是Java虚拟机,是一种基于堆栈的语言。此外,.NET Framework基于MSIL,它也是基于堆栈的虚拟机和语言。

As an Embedded Scripting Language

我一直在C#中编写FORTH的子集,使用不同的样式(到目前为止,宏,间接线程和直接线程)。我希望它非常小,可以移植到不同的语言和环境,而且非常简单的东西应该能够做到这一点。解析器是一个简单的字符串拆分函数,然后解释每个单词(第一种方式),或者将每个单词编译成字典(第二种方式)。两者都有自己的优势。

It's Functional

那就对了。你听到了我的话。纯粹功能意味着,在相同输入的情况下,您可以获得相同的输出,并且不会产生副作用。在FORTH的基于零点堆栈的语言中,至少对于大多数单词而言,给定堆栈作为输入,在运行单词之后,您将获得与输出相同的堆栈。因此,它具有功能性,所有数学保证的属性都随之而来! FORTH可以做得更好。

可以创建一个Haskell-Forth吗? - 纯功能的Haskell语言,但重新表达为基于堆栈的语言?它已经纯粹作为基于堆栈的语言功能。 Hmmmmm ...

Object-Oriented Research

因为FORTH允许您根据需要完全重新定义语言,并且它是简单机制的深层组合,它可以产生许多不同的面向对象风格。随着OOP的发展,在FORTH上实施OOP已经进行了大量的实验,其中一些我从未在其他任何地方听说过,并且很有趣。不幸的是,我还没有深入研究这一点。如果你有兴趣,你可以挖掘4th Dimensions期刊,了解有关OOP的有趣观点和想法,因为它刚刚开始。

我很快就看了这些

Bringing Your Optimized Software to the Hardware Level

查尔斯·摩尔是FORTH的父亲,他是第一批基于堆栈的语言之一,他一生都在优化软件开发以及他能用它做些什么,甚至构建了一个144核心处理器来实现他最新的基于堆栈的语言。

Research Into Optimization

Joy编程语言的作者使用他的基于堆栈的语言来研究代码优化,堆栈语言的零点性质部分地实现了这一点。而Joy是我最尊重的基于堆栈的语言之一,因为它纯粹是功能性的。

这是Joy简介:

Joy是一种纯函数式编程语言。尽管所有其他函数式编程语言都基于函数对参数的应用,但Joy基于函数的组合。所有这些函数都将堆栈作为参数并生成堆栈作为值。因此,Joy的大部分看起来像普通的后缀表示法。但是,在Joy中,函数可以从堆栈中使用任意数量的参数,并在堆栈上留下任意数量的结果。适当程序的串联表示程序表示的功能的组成。 Joy的一种数据类型是引用程序,其中列表是一种特殊情况。有些函数期望在堆栈顶部引用程序并以多种不同的方式执行它们,有效地通过dequoting。因此,在其他函数式语言使用抽象和应用程序的情况下,Joy使用引用和组合器 - 执行dequotation的函数。因此,没有命名的形式参数,没有实际的形式参数替换,也没有名称 - 值对的环境。 Joy中的组合器与其他语言中的函数或高阶函数非常相似,它们最小化了递归和非递归定义的需要。因为不需要环境,Joy具有非常简单的代数,并且其程序可以通过手工和其他程序轻松操作。许多程序首先构建另一个程序然后执行。

Because That's The Shape of the Problem (or the Machine!)

每个范例都有它的形状,每个要解决的问题都有它的形状。一旦你将你的问题分解为原子碎片,它们就会最适合兼容的范例。使用基于堆栈的语言来表示基于堆栈的问题的基于堆栈的解决方案。

Performance

性能是JAVA和.NET都基于堆栈语言的隐藏原因之一。我认为另一个原因是因为基于堆栈的语言更容易进行JIT-ting,编译和优化。大多数CPU指令都不能有效地实现堆栈操作吗?我相信,这是基于堆栈或基于寄存器的重点。

One Shape

当您的所有代码都是基于堆栈的时,它没有阻抗不匹配。你不必翻译。我的意思是Homoiconicity,这意味着预处理器不是完全独立的语言,而是在C ++中,语言可以自己操作,而用于预处理(或实现宏)的语言与您用来编写自己的语言相同。主要代码文件。你可以编写代码。您可以编写编写代码的代码。或者,如果你愿意,你可以进一步深入。在每个级别,您都可以使用相同的FORTH。显然,Lisps也是如此,尽管我在那个领域做得还不够。 (我最终希望混合LISP和FORTH - 我想知道我们是否需要FORTH中的所有LISP宏功率)。

FORTH

多年来我一直在研究这种语言,我对它感到震惊。在这里,我不是在讨论通过其在主流中的使用和标准化而普及的FORTH。在这里,我真的在谈论FORTH,由其创造者Charles Moore设想并定义,他将其视为优化语言和探索简单和优化深度的工具,并说实话,已经走了一段距离在我们前面。到目前为止,似乎我们永远不会赶上,但如果我们能够这样做的话,我们还有很多东西要向他学习。他花了一辈子的时间找到了,可能需要我们几个才能弄清楚我们是否能找到一位大使/翻译。无论如何...

Charles Moore编写了自己的BIOS,操作系统,应用程序库和VSLI工程设计软件,并使用该软件设计了自己的144核心芯片。而且我相信至少有一项专利来自它 - 你知道,他是一位伟大的探险家,他已经像我所知道的其他人一样探索了优化。

如果你把这一个网站,杰夫福克斯的Ultratechnology,看看这篇文章,1x Forth,杰夫福克斯对查尔斯摩尔的采访。在这次采访中,他解释了他是如何不再使用“其他”的,这听起来很疯狂,但这就是他的优化带给他的程度 - 他在想“而是我只是使用这个操作码,而另一个技巧,它就是更简单,更快捷,我从我的操作代码中删除了一个单词“。

在那个网站上,你必须从很多地方收集,但你最终明白他们已经优化了FORTH到目前为止,他们已经比这里提高了10%,比那里提高了10%,遗漏了40%的其他地方的代码,......令人惊讶的结果是,在某些情况下,他们的代码运行速度比竞争代码快100倍。

如果他们被迫运行同样的垃圾,就像真正的基准会强制一样,它会产生更多类似的时间,但就是这样。使用FORTH已经导致重构和优化成为一种做事的方式,他们最终执行速度更快,因为他们刚刚遗漏了大量的垃圾,肮脏,臃肿,残酷......

学习这种“方式”只是为了回到试图弄清楚为什么我们必须安装如此多的MB操作系统,以及如此多的MB开发环境,然后才能说出“Hello,World!”

Post-Script on PostScript

哦,是的,我忘了提。 PDF和PostScript都基于堆栈语言,它必须足够紧凑并且具有足以在计算刚刚开始时在“古老”硬件上运行的性能。 PostScript ...简约,强大,高效,实用!

© www.soinside.com 2019 - 2024. All rights reserved.