【问题标题】:Looking for a functional language [closed]寻找功能语言[关闭]
【发布时间】:2010-11-12 00:40:26
【问题描述】:

我是一名主要使用 C++ 的科学家,但我想找到一种更好的语言。我正在寻找建议,我什至不确定我的“梦想语言”是否存在,但这是我的愿望清单;

重要特征 (按重要性排序)

1.1:性能:对于科学来说,性能非常重要。我完全理解生产力的重要性,不仅是执行速度,而且当你的程序必须运行几个小时时,你就不能用 Python 或 Ruby 编写它。它不需要像 C++ 一样快,但它必须相当接近(例如:Fortran、Java、C#、OCaml...)。

1.2:高级而优雅:我希望能够尽可能地专注于科学并获得清晰的代码。我也不喜欢像 Java 这样冗长的语言。

1.3:主要是函数式:我喜欢函数式编程,我认为它非常适合我的风格和科学编程。我不在乎语言是否支持命令式编程,这可能是一个加分项,但它必须关注并鼓励函数式编程。

1.4:可移植性:应该在 Linux(尤其是 Linux!)、Mac 和 Windows 上运行良好。不,我不认为 F# 在带有单声道的 Linux 上运行良好,而且我不确定 OCaml 在 Windows 上运行良好;)

1.5:面向对象,最好遵循“一切都是对象”的理念: 不久前,当我不得不处理纯 C 语言时,我意识到我是多么喜欢面向对象编程。我喜欢坚定致力于面向对象编程的语言,而不仅仅是胆小的支持。

不是很重要,但会很好的事情

2.1:“不太强”类型:我发现 Haskell 的强类型系统很烦人,我喜欢能够进行一些隐式转换。

2.2:工具: 好的工具总是加分项,但我想这真的取决于语言。我使用轻量级编辑器 Geany 与 Haskell 一起玩,我从不觉得有缺陷。另一方面,我不会对 Java 甚至 Scala 做同样的事情(特别是 Scala,似乎缺乏好的工具,这真的很可惜)。 Java 在这里确实是排名第一的语言,使用 NetBeans 和 Javadoc,使用 Java 编程既简单又有趣。

2.3:垃圾收集,但没有虚拟机翻译或编译。我对虚拟机没有任何反感,但领域中的两大巨头各有各的问题。在纸面上,.net 框架似乎要好得多,并且特别适合函数式编程,但实际上它仍然非常以 Windows 为中心,并且对 Linux/MacOS 的支持terrible不如应有的好,所以这并不值得考虑。 Java 现在是一个成熟的 VM,但它在某些层面上让我很恼火:我不喜欢它处理可执行文件、泛型的方式,而且它编写的 GUI 很糟糕(尽管这些东西还不错)。

【问题讨论】:

  • 虚拟机与 GUI 究竟有什么关系。 JVM 将在甚至没有屏幕的机器上运行。
  • 如果您最近没有跟上 C# 的步伐,请注意最新版本比您想象的更实用。你也许可以用你喜欢的 C# 风格编写程序。
  • @Drew:也许吧,但是 Mono 支持吗?
  • 您需要什么类型的计算才能快速执行?有很多数学库可以快速完成某些事情,即使是像 python 这样的“慢”语言。
  • 相当大的模拟。我经常需要生成数以亿计的随机数。 Python 是我的第二语言,我真的很喜欢它。我知道您可以将 C/C++ 与它一起使用,但我不确定它是否适用于我的情况(我可能会就此提出一个新问题,这可能会更容易)。

标签: programming-languages functional-programming


【解决方案1】:

在我看来,有三个可行的候选者:Haskell、Standard ML、OCaml。 (Scala 退出的原因是它可以编译为 JVM 代码,因此当程序必须运行数天时,它的速度不太可能足够快。) 所有这些都主要是功能性的。我会在我有知识的地方发表评论。

高性能

  • OCaml 在所有情况下都能提供最稳定的性能,但性能很难提高。你得到的就是你得到的:-)

  • Haskell 具有最佳的并行性能,可以很好地利用 8 核或 16 核机器。如果你的未来是平行的,我敦促你掌握你对类型系统的厌恶,并学会有效地使用 Haskell,包括 Data Parallel Haskell 扩展。

    Haskell 性能的缺点是很难预测评估惰性函数程序所需的空间和时间。有许多出色的分析工具,但仍可能需要付出巨大的努力。

  • 带有 MLton 编译器的标准 ML 提供了出色的性能。 MLton 是一个全程序编译器,做得非常好。

高级优雅

  • 从语法上讲,Haskell 是明显的赢家。然而,类型系统中充斥着最近实验的残余物。然而,类型系统的核心是高级且优雅的。 “类型类”机制特别强大。

  • 标准 ML 的语法丑陋,但类型系统和语义非常干净。

  • 从语法和类型系统的角度来看,OCaml 是最不优雅的。过去实验的遗骸比 Haskell 更引人注目。此外,标准库并不像您预期​​的那样支持函数式编程。

主要功能

Haskell 是纯函数式的;标准 ML 非常实用; OCaml 主要是功能性的(但要注意可变字符串和库中一些令人惊讶的遗漏;例如,列表函数对于长列表是不安全的)。

便携性

这三个都在 Linux 上运行良好。 Haskell 开发人员使用 Windows 并且得到了很好的支持(尽管这让他们很痛苦)。我知道 OCaml 在 OSX 上运行良好,因为我使用了一个用 OCaml 编写的应用程序,该应用程序已移植到 OSX。但我在这里知之甚少。

面向对象

在 Haskell 或 SML 中找不到。 OCaml 在核心语言上移植了一个沼泽标准的 OO 系统,与其他语言没有很好的集成。

你没有说你为什么热衷于面向对象。 ML 仿函数和 Haskell 类型类提供了 C++ 中的一些封装和多态性(也称为“泛型编程”)。

可以颠覆的类型系统

所有三种语言都提供了不安全的强制转换。在所有这三种情况下,它们都是获取核心转储的好方法。

我希望能够进行一些隐式转换。

我想你会发现 Haskell 的类型类系统符合你的喜好——你可以获得一些类似于隐式转换的效果,但安全。特别是,数字和字符串文字可以隐式转换为您喜欢的任何类型。

工具

Haskell 有相当不错的分析工具。标准机器学习有蹩脚的工具。 OCaml 基本上具有标准的 Unix 分析和无法使用的调试器。 (调试器拒绝跨越抽象障碍,它不适用于本机代码。)

我的信息可能已过时;工具图片一直在变化。

垃圾收集并编译为本机代码

检查。没有什么可以选择的。

推荐

克服您对安全、可靠的类型系统的厌恶。研究 Haskell 的类型类(Wadler 和 Blott 的原始论文和 Mark Jones 的教程可能很有启发性)。 深入了解 Haskell,并确保在 Hackage 了解大量相关软件。

【讨论】:

  • 我非常喜欢 Haskell,我同意你的观点。我希望在 Haskell 中将输入字符串实习成唯一的符号或 id 更合理,然后对解析的输入执行一些纯计算,稍后以只读方式使用字符串。你现在有一个贯穿整个程序的 monad。呸。 Scala 可能比 Ocaml 或 Haskell 快得多,具体取决于实现技术。但我同意高级的、纯函数式的 Scala 往往比 Ocaml 或 Haskell 稍慢。
  • 感谢您的回答。我可能会再看看 Haskell 的类型系统。
  • @wrang-wrang: Gensym 在 Haskell 中一直是个痛点,但我认为如果你将解析后的输入与从 UId 到字符串的映射结合起来,你实际上可以将 monad 包含在非常窄的范围内,例如, 编写一个 String -> (ParseTree, Data.Map Unique String) 类型的纯函数,它在内部使用状态单子。
  • “Scala 退出的原因是它可以编译为 JVM 代码,因此当程序必须运行数天时,它的速度不太可能足够快。”这是基于 1.6 JVM 的经验,还是基于它曾经如何回到黑暗时代?
  • @Peter:部分是在黑暗时代,部分是因为 JVM 不支持正确的尾调用,因此函数式程序(执行大量尾递归)往往表现不佳。见stackoverflow.com/questions/105834/…。我的理解是,要从 Scala 中获得最佳性能,您必须放弃尾调用。
【解决方案2】:

试试 Scala。它是一种在 JVM 中运行的面向对象的函数式语言,因此您可以访问曾经用 Java 编写的所有内容。它具有您所有的重要功能,并且是其中一项不错的功能。 (显然不是#2.2 :) 但这可能会很快变得更好。)它确实有非常强大的类型,但是通过类型推断它并不会真正妨碍你。

【讨论】:

  • Scala 满足您的所有要求,除了 2.2。它具有正确的强类型,因为它用于支持程序员编写更干净、更简单的代码,而不是强迫他们跳过障碍。对于大致相同的性能,它比 Java 简洁得多。它支持并鼓励功能性风格,同时仍然允许非功能性风格。
【解决方案3】:

你刚刚描述了 Common Lisp...

【讨论】:

    【解决方案4】:

    如果您喜欢在大多数事情上使用列表,并且关心性能,请使用 Haskell 或 Ocaml。尽管 Ocaml 在堆上的浮点数由于 VM 设计而需要装箱(但浮点数组和纯浮点记录没有单独装箱,这很好)方面受到很大影响。

    如果您愿意使用数组而不是列表,或者计划使用可变状态进行编程,请使用 Scala 而不是 Haskell。如果您正在寻找编写线程多核代码,请使用 Scala 或 Haskell(Ocaml 要求您 fork)。

    Scala 的列表是多态的,因此 int 列表实际上是装箱的 Int 对象的列表。当然,您可以在 Scala 中编写自己的 int 列表,速度也一样快,但我假设您更愿意使用标准库。 Scala 在 JVM 上确实有尽可能多的尾递归。

    我认为 Ocaml 在 Vista 64 上失败了,我认为是因为他们只是更改了最新版本(3.11.1?)中的链接器,但早期版本运行良好。

    如果您使用夜间构建,目前 Scala 工具支持存在缺陷,但应该很快就会好。有eclipse和netbeans插件。我正在使用 emacs 代替。我过去成功使用过 eclipse 和 netbeans 调试器 GUI。

    Scala、Ocaml 或 Haskell 都没有真正出色的标准库,但至少您可以轻松地在 Scala 中使用 Java 库。如果你使用 mapreduce,Scala 会在集成上胜出。 Haskell 和 Ocaml 有合理数量的 3rd 方库。 Haskell 中有 2-3 种类型的 monad 有不同命名的组合器,这让我很恼火。

    http://metamatix.org/~ocaml/price-of-abstraction.html 可能会说服你继续使用 C++。可以编写性能与 Java/C++ 几乎相同的 Scala,但不一定是高级函数式或 OO 风格。

    http://gcc.gnu.org/projects/cxx0x.html 似乎暗示 auto x = ... (表达式的类型推断)和 lambdas 是可用的。带有 boost 的 C++0x,如果你能忍受的话,看起来很实用。 C++ 高性能模板滥用库的缺点当然是编译时间。

    【讨论】:

      【解决方案5】:

      在我看来,您的要求很好地描述了 ocaml,除了“不太强”的打字。至于工具,我使用并且喜欢 emacs 的 tuareg 模式。 Ocaml应该在windows上运行(我自己没用过),和F#、FWIW很像。

      我也会考虑围绕语言的生态系统。在我看来,Ocaml 的主要缺点是它没有一个庞大的社区,因此缺乏大量的第三方模块库,而这些库正是使 python 如此方便的一部分。必须编写自己的代码或修改您在 Internet 上找到的其他人的一次性原型模块,这可能会占用您通过编写漂亮的函数式语言节省的一些时间。

      【讨论】:

      • IMO,库支持/3rd-party 模块可用性是 F# 的一张真正的王牌。
      【解决方案6】:

      您可以在单声道上使用 F#;也许值得一看?我知道单声道不是 100% 完美(从来都不是),但它非常远非“糟糕”;大多数差距都在 WCF/WPF 之类的东西上,我怀疑你是否想从 FP 中使用它们。这似乎提供了你想要的很多东西(除了显然它在 VM 中运行 - 但你在讨价还价中获得了大量可用的库(即大部分 .NET) - 比它所基于的 OCaml 容易得多) .

      【讨论】:

      【解决方案7】:

      我仍然会选择 Python,但使用 NumPy 或其他一些外部模块进行数字运算,或者在 Python 中执行逻辑并在 C/汇编程序中执行热点。

      您总是为了舒适而放弃循环,舒适度越高,循环越多。因此,您的要求是互斥的。

      【讨论】:

      • 我强烈不同意我的要求是相互排斥的,至少现在不是了。许多高级语言,例如 Haskell、OCaml 和 Scala,都可以生成非常快速的程序。当然,它们不是动态的,但我不在乎。
      • 您给出明确规定的性能要求,任何语法糖都将花费时钟周期,无论您做什么。有些可能比其他更快,但它总是比直接用该平台的汇编语言实现的算法慢。当您提出例如 Java 足够快的概念时,我可以向您保证,使用 Python 和用 C 编写的热点或使用专门的数字模块将优于除 C/Assembler 之外的任何其他语言的任何其他实现。然而,任何支持 FFI 的语言都可以做到这一点。
      【解决方案8】:

      我认为 Common Lisp 非常适合您的描述。

      1.1:性能:现代 CL 实现几乎与 C 相当。还有与 C 库交互的外部函数接口,并且已经完成了许多绑定(例如 GNU 科学库)。

      1.2:高级和优雅:是的。

      1.3:主要是功能性的:是的,但您也可以在需要时“获得命令式”; CL 是“多范式”。

      1.4:可移植性:有多种实现对每个平台的不同支持。一些链接位于CLiki 和ALU Wiki。

      1.5:面向对象,最好是在“一切都是对象”的理念下:CLOS,Common Lisp Object System,比任何“curly”语言都更接近“面向对象”,并且还具有一些特性你会非常想念其他地方,比如多方法。

      2.1:“不太强”类型:CL 具有动态、强类型,这似乎是您想要的。

      2.2:工具:Emacs + SLIME(Emacs 的高级 Lisp 交互模式)是一个非常不错的免费 IDE。还有一个Eclipse插件(Cusp),商业的CL实现也经常自带IDE。

      2.3:垃圾被收集,但在没有虚拟机的情况下翻译或编译。您将要处理的 Lisp 映像是一种 VM,但我认为这不是您的意思。

      另一个优势是增量开发:您有一个 REPL(读取-评估-打印-循环)正在运行,它为正在运行的映像提供了一个实时接口。您可以即时编译和重新编译各个函数,并检查实时系统上的当前程序状态。您不会因为编译而被强制中断。

      【讨论】:

      • 我也考虑过 Common Lisp(请参阅我的另一篇文章),但我会说当前的开发工具很烂。 Slime 安装起来很痛苦,而且用户群太小,无法支持很多 3rd 方软件,多线程无处不在,这取决于你选择的实现等等。这就是我建议放弃(基本上)Linux 的原因要求,只是去窗户。如果 Mono 不够用,那么您始终可以在 Linux 上运行 VM。
      • 呸。我不知道你一直在做什么,但让 Slime 工作是轻而易举的事。多线程需要阅读一些手册,但这并不罕见。那里也有很多发展。您还可以在 Planet Lisp、Lisp 论坛或 IRC 等找到一个不错的社区。​​span>
      【解决方案9】:

      简短版:D 编程语言

      Yum Yum Yum,这是一大套要求。

      您可能知道,从技术角度来看,面向对象、高级语义、性能、可移植性以及您的所有其他要求往往无法融合在一起。让我们将其拆分为不同的视图:

      语法要求

      1. 面向对象的表示
      2. 内存管理复杂度低
      3. 允许函数样式
      4. 不是 Haskell(该死)

      后端要求

      1. 科学快速
      2. 垃圾收集

      在此基础上,我会推荐D 编程语言,它是 C 的继承者,试图成为所有人的一切。

      This article on D 是关于它的函数式编程方面。它是面向对象的,垃圾收集并编译为机器代码,速度很快!

      祝你好运

      【讨论】:

        【解决方案10】:

        Clojure 和/或 Scala 是 JVM 的理想选择

        【讨论】:

          【解决方案11】:

          我假设您对您提到的语言已经足够熟悉,已将它们排除在外。鉴于此,我认为没有一种语言可以满足您的所有期望。但是,您仍然可以查看几种语言:

          1. Clojure 这确实是一门非常好的语言。它的语法基于 LISP,运行在 JVM 上。

          2. D 这就像 C++ 做得对。它具有您想要的所有功能,只是它在函数式编程方面有点弱。

          3. Clean 这在很大程度上基于 Haskell,但消除了 Haskell 的一些问题。缺点是不够成熟,库也不多。

          4. Factor在语法上它基于 Forth,但支持类似 LISP 的函数式编程以及对类的更好支持。

          【讨论】:

            【解决方案12】:

            看看Erlang。最初,Erlang 旨在构建容错、高度并行的系统。它是一种函数式语言,包含不变性和一流的函数。它有一个官方的 Windows 二进制版本,并且可以为许多 *NIX 平台编译源代码(例如,有一个 MacPorts 版本)。

            在高级特性方面,Erlang 支持列表推导、模式匹配、保护子句、结构化数据和其他您期望的功能。它在顺序计算中相对较慢,但如果您正在进行并行计算,那就太棒了。 Erlang 确实在 VM 上运行,但它在自己的 VM 上运行,这是发行版的一部分。

            Erlang 虽然不是严格面向对象的,但确实受益于 OO 思维方式。 Erlang 使用一个叫做进程的东西作为它的并发单元。 Erlang 进程实际上很像本地线程,只是开销要少得多。每个进程都有一个邮箱,将发送消息,并将处理这些消息。将进程视为对象很容易。

            我不知道它是否对科学图书馆有很大影响。它可能不太适合您的需求,但它是一种很酷的语言,似乎很少有人知道。

            【讨论】:

              【解决方案13】:

              你确定你真的需要函数式语言吗?我的大部分编程都是用 lisp 进行的,这显然是一种函数式语言,但我发现函数式编程更多的是一种思维定势,而不是一种语言特性。我现在正在使用 VB,我认为它是一种出色的语言(速度、支持、IDE),并且我基本上使用了与在 lisp 中所做的相同的编程风格——函数调用调用其他函数的其他函数——并且函数通常是 1 -5 行长。

              我确实知道 Lisp 具有良好的性能,可以在所有平台上运行,但是就图形、多线程等功能的最新支持而言,它有些过时了。

              我看过 clojure,但如果你不喜欢 java,你可能不会喜欢 clojure。它是一种在 java 之上实现的函数式 Lisp 风格的语言——但你可能会发现自己一直在使用 java 库,这增加了 java 的冗长性。我喜欢 lisp,但我不喜欢 clojure,尽管大肆宣传。

              您还确定自己的性能要求吗? Matlab 是用于大量科学计算的优秀语言,但它有点慢,我讨厌阅读它。您可能会发现它对原型/场景/子单元非常有用,但尤其是与其他语言结合使用时。

              【讨论】:

              • 我想说这不仅仅是一种心态。例如,我认为函数式语言应该支持闭包,并且应该可以轻松地将函数用作其他函数的 参数。缺乏尾递归也会阻碍函数式风格。
              • 心态绝对是一个重要的组成部分。自从学习了 Scala(它本身只是一种不纯的函数式语言,因为它具有函数式语言的特性,同时还可以让你根据需要以非函数式风格编写),我用其他语言编写的代码在风格上变得更加函数式。即使在 PHP 中,它也是功能最少的语言之一!
              • 没有尾递归是什么意思?尾递归就是函数调用发生的地方。问题是编译器是否足够聪明以消除对尾递归的递归调用——这是一个简单的编译器优化,我相信 CLR 有它。无论如何,这是一个编译器优化问题,而不是语言问题。
              • 如果一种语言不能保证尾递归,那么你就不能真正将递归用作循环结构,因为它太昂贵了。自然的替代方案是具有可变数据的命令式样式。有些语言需要将某些形式的递归实现为尾调用,而有些则不需要。例如,我相信 gcc 可以找到一些尾调用,但是因为 C 没有强制要求,所以你仍然会非常小心使用递归。
              • 实际上,我更喜欢 C/C++ 而不是 VB。 VB 几乎是一门好的科学语言不应该的一切。虽然拥有一个 GUI 很有趣,但大多数科学程序都没有。它在 windows 上运行得非常频繁(学术界的许多科学家,如果不是大多数,都与 Unices 合作)。 MatLab 比 C 慢,但性能通常是合理的,但是我使用 Python 和 Numpy 来解决我遇到的类似 Matlab 的问题。
              【解决方案14】:

              您的许多要求都是基于道听途说的。一个例子:Mono 是“可怕的”的想法。

              http://banshee-project.org/

              这是许多 Linux 发行版的官方媒体播放器。它是用 C# 编写的。 (他们甚至没有公开的 Windows 版本!)

              您关于各种语言的相对性能的断言同样令人怀疑。并且要求一种语言不使用虚拟机是非常不现实的,也是完全不可取的。甚至操作系统也是一种运行应用程序的虚拟机,它将机器的硬件设备虚拟化。

              虽然您因提及工具而获得积分(尽管没有足够的优先级)。正如 Knuth 所观察到的,关于语言的第一个问题是“调试器是什么样的?”

              【讨论】:

              • 是的,我已经习惯了因为提供事实而被否决!
              • 你抱怨道听途说,然后提供一个轶事来反驳它。然后,当它们是非常不同的概念时,您会用语言级别的 VM 来混淆操作系统。 “非常不切实际,完全不受欢迎”也不是一个提供事实的陈述。
              • 所以你说你根本不明白我说的话。我可能不得不忍受这种情况。
              • 您可能想查找“模棱两可”这个词。看,免费的事实不断涌现,即使对于那些不想要它们的人!
              • “有两种或多种解释,通常用于误导或混淆”,这就是您对“虚拟机”一词所做的事情。我建议您查找“事实”。
              【解决方案15】:

              查看您的要求,我建议在 Mono 或运行 Windows 的虚拟机上使用 VB。正如之前的发帖人所说,关于一种语言,首先要问的是“调试器是什么样的”,而 VB/C# 拥有最好的调试器。只是所有这些微软员工都在调试调试器,并让附近的团队(没有双关语)修复它的结果。

              VB 和 C# 最好的地方在于大量的开发人员工具、社区、谷歌帮助、代码示例、库、与之交互的软件等。过去我使用过各种各样的软件开发环境27 年,唯一接近的是 Xerox Lisp 机器环境(更好)和 Symbolics Lisp 机器(更差)。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-06-10
                • 2013-01-24
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多