C++11中的函数式编程,F#风格

10

我一直在研究C++11中的新功能,看起来很可能可以使用它以非常函数式的编程风格进行编程。我已经习惯使用F#中的List、Seq、Array等类型,我认为这些类型的成员们也可以被移植到某种C++11模板中。与使用F#进行混合函数式编程相比,您认为使用C++11存在哪些问题或优点?也许当C++11发布后,Boost的人会推出一个新的functional库。


3
你所提到的参考资料(STL算法,顺便说一下,它不是一个类)是关于已经存在并且在C++中是标准的头文件。也就是说,没有什么新东西。新的C++标准只是简化了传递给已有算法的函数对象的创建过程。 - David Rodríguez - dribeas
5个回答

15

尝试在C ++中以函数式风格编程的最大问题是它不支持尾递归。在函数式语言中,正确尾递归时无需担心堆栈溢出,但在C ++中,您必须始终担心这一点。因此,许多“函数式”类型算法将变得笨拙或繁重。


2
并不完全正确。如今大多数流行的C++编译器都能够正确处理尾递归,但可能需要您指定额外的优化标志,例如“-O2”。 - Samee
3
这是真的。无论编译器经过什么优化,语言都不提供此功能,因此依赖它是很危险的。 - Christopher
问题在于RAII与尾调用优化不兼容。F#中使用try...finally也存在同样的问题,但由于结构的明确性更加明显。 - Joh
不是这样的。编译器会将尾调用转换为循环,而循环与 RAII 很好地配合使用。你必须行使一些判断力,但这适用于每种语言。 - Christopher

6
以下是我在尝试使用C#编写函数式代码时遇到的一些问题,以及我在仍然使用C++时遇到的一些好处:
  1. 模式匹配不足。习惯了这种功能后,没有它会让我发疯。
  2. 元组缺乏语法糖。
  3. 记录复制和一次性设置字段的语法不足。
  4. 列表和数组缺乏语法。这适用于构造函数和模式匹配。
  5. 没有垃圾回收机制,以及不安全的内存访问。不受垃圾回收机制的限制是一个优势,但我永远不会忘记第一次在认为没有错误的C++代码上运行Valgrind时收到的报告。
  6. 理解模板代码并不是所有人都可以轻松掌握的技能。我没有问题理解自己的代码,但每当我看到STL、boost或cgal的实现时,我就会想知道他们在使用什么语言。我的C++和他们的C++不在同一个世界中。
  7. 处理使用另一个版本的boost(或任何使用模板的库)的库时完全没有乐趣。
  8. 分离头文件/实现文件的冗长。
  9. C++中的类型推断不如F#等语言。我知道在C++11中已经有所改进,但据我所知,它类似于C#中的var,这对于品尝F#风格的推断来说还不够。
  10. 计算表达式不足,包括序列表达式、推导式、异步等...

如果有几个问题实际上可以使用一些模板和预处理器魔术在C++中解决,那么这并不会让我感到惊讶,但在生产环境中,除非你有非常有冒险精神和容忍度的同事,否则你无法真正使用这些技巧。

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


5

谢谢!一个完整实现的起点可以是boost的range和iterator库,两者的某种组合。 - Daniel Earwicker

3
你认为在使用C++0x和像F#这样的混合函数式编程风格中,有哪些优缺点问题?
40年前,在Lisp的背景下就曾经讨论过上行funarg问题

0

我想象一下,在C++0x中实现某些函数式语言常见的优化(如公共子表达式消除),会是一件有趣的事情。


大多数C和C ++编译器都执行共同子表达式消除(CSE)和全局共同子表达式消除(GCSE)。这不是问题所在。问题涉及部分函数应用和尾递归。 - Christopher

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接