【问题标题】:Functional programming in C++11, F# styleC++11 中的函数式编程,F# 风格
【发布时间】:2010-11-08 12:30:15
【问题描述】:

我一直在研究 C++11 中的新特性,看起来真的可以使用它以非常函数式的编程风格进行编程。我已经习惯在 F# 中使用 List、Seq、Array 类型,而且我认为没有理由不能将它们的成员移植到某种 C++11 模板中。在使用 C++11 与 F# 之类的混合函数式编程风格时,您看到了哪些问题或优势?一旦 C++11 出现,也许 Boost 家伙会创建一个新的functional

【问题讨论】:

  • 您指向的引用(STL 算法,不是 BTW 类)是关于 C++ 中已经存在且标准的标头。也就是说,没有什么新鲜事。新的 C++ 标准只是简化了传递给现有算法的函子的创建。

标签: c++ c++11 f# functional-programming


【解决方案1】:

尝试在 C++ 中以函数式编程的最大问题是它不支持尾递归。在函数式语言中,当您正确地进行尾递归时,您不必担心堆栈爆炸,但在 C++ 中,您总是需要担心这一点。因此,许多“函数式”类型的算法会很笨拙或笨重。

【讨论】:

  • 不完全正确。当今最流行的 C++ 编译器将正确处理尾递归,但可能需要您指定额外的优化标志,如“-O2”。
  • 这是真的。不管编译器会做什么优化,语言都没有为这个特性提供工具,所以依赖它是危险的。
  • 问题在于 RAII 与尾调用优化不兼容。同样的问题存在于 F# 中,使用 try...finally,但由于结构的明确性,它更加明显。
  • 不正确。编译器将尾调用转换为循环,并且循环与 RAII 一起正常工作。您必须做出一些判断,但每种语言都是如此。
【解决方案2】:

以下是我在尝试用 C# 编写函数式代码时遇到的一些问题,以及我仍在使用 C++ 时的一些好东西:

  1. 缺乏模式匹配。一旦你习惯了它,不拥有它会让我发疯。
  2. 元组缺少语法糖。
  3. 缺少一次性复制记录和设置字段的语法。
  4. 缺少列表和数组的语法。这适用于构造函数和模式匹配。
  5. 没有 GC,并且内存访问不安全。不受 GC 的限制是一个优势,但想起我第一次运行 Valgrind 时在 C++ 代码上得到的报告,我认为这是无错误的,这让我永远感到害怕。
  6. 并非所有人都能理解模板代码。我的理解没有问题,但是每当我研究 STL、boost 或 cgal 的实现时,我发现自己想知道他们使用的是什么语言。我的 C++ 和他们的 C++ 不在同一个世界。
  7. 处理使用另一个版本的 boost(或任何使用模板的库)的库完全没有乐趣。
  8. 单独的头文件/实现文件的详细程度。
  9. C++ 中的类型推断没有达到例如F#。我知道它在 C++11 中得到了改进,但据我了解,它类似于 C# 中的 var,一旦你尝过 F# 风格的推理,这还不够。
  10. 缺少计算表达式,包括序列表达式、推导式、异步...

如果使用某些模板和预处理器魔法在 C++ 中实际上可以实现其中的几个点,我不会感到惊讶,但是除非您有非常冒险和宽容的同事,否则您不能真正在生产环境中使用这些点。

我之前是个死忠的 C++ 爱好者。然后我开始使用带有模板的泛型编程和使用函数对象的高阶函数。只是写得太累了。在我尝试了一种函数式语言之后,我再也没有回头。

【讨论】:

    【解决方案3】:

    【讨论】:

    • 谢谢!完整实现的起点是 boost 的范围和迭代器库,两者的某种组合。
    【解决方案4】:

    对于混合函数式编程风格,您认为使用 c++0x 与 f# 之类的东西有哪些优势?

    upward funarg problem,40 年前在 Lisp 的背景下争论不休!

    【讨论】:

      【解决方案5】:

      我想在 C++0x 中实现函数式语言常见的某些优化(如常见的子表达式消除)会是……有趣的……。

      【讨论】:

      • 大多数 C 和 C++ 编译器都执行 CSE 和 GCSE。这不是问题。问题涉及部分函数应用和尾递归。
      猜你喜欢
      • 1970-01-01
      • 2017-10-02
      • 2011-02-17
      • 2012-11-06
      • 1970-01-01
      • 1970-01-01
      • 2022-11-30
      • 2016-01-11
      • 2014-10-20
      相关资源
      最近更新 更多