【问题标题】:Why is functional programming good? [closed]为什么函数式编程好? [关闭]
【发布时间】:2023-03-02 23:51:01
【问题描述】:

我注意到许多函数式编程狂热分子坚持的某些核心概念:

  • 回避状态

  • 避免可变数据

  • 尽量减少副作用

  • 等等……

我不只是想知道还有哪些其他东西使函数式编程变得更好,而且为什么这些核心思想是好的?为什么最好避免状态,以及其他?

【问题讨论】:

    标签: functional-programming


    【解决方案1】:

    简单的答案是,如果您无需担心额外的状态,您的代码就更易于推理。更简单的代码更容易维护。您无需担心特定代码(如函数)之外的事情来修改它。这对测试等事情有非常有用的影响。如果您的代码不依赖于某些状态,则为该代码创建自动化测试会变得更加容易,因为您无需担心初始化某些状态。

    使用无状态代码还可以更轻松地创建线程程序,因为您无需担心两个执行线程同时修改/读取共享数据。您的线程可以运行独立的代码,这可以节省大量的开发时间。

    本质上,避免状态会创建更简单的程序。在某种程度上,“移动部分”(即代码行可以交互的方式)更少,因此这通常意味着代码更可靠并且包含更少的错误。基本上,代码越简单,出错的可能性就越小。对我来说,这就是编写无状态代码的本质。

    创建无状态的“功能性”代码还有很多其他原因,但对我来说,它们都归结为简单。

    【讨论】:

    • 是否应该提到并发更容易正确执行?
    • +1。说得好,奥莱克西。
    【解决方案2】:

    除了@Oleksi 所说的之外,还有另一件重要的事情:引用透明性和事务性数据结构。当然,您不需要函数式编程语言来执行此操作,但使用它们会更容易一些。

    Purely functional data structures 保证保持不变 - 如果一个函数返回一棵树,它将始终是同一棵树,并且所有进一步的转换都会创建它的新副本。以这种方式回溯到数据结构的任何先前版本要容易得多,这对于许多基本算法很重要。

    【讨论】:

      【解决方案3】:

      非常普遍,函数式编程意味着:

      • 鼓励使用(一流)功能
      • 不鼓励使用(可变)状态

      为什么突变是个问题?想一想:mutation 之于数据结构就像 goto 之于控制流。即,它允许您以一种相当非结构化的方式任意“跳转”到完全不同的事物。因此,它偶尔有用,但大多数时候对可读性、可测试性和组合性有害。

      【讨论】:

      • +1 用于将可变状态与 goto 进行比较!
      【解决方案4】:

      一个典型的功能特性是“没有子类型化”。虽然将其称为功能听起来有点奇怪,但出于两个(某种程度上相关的)原因:

      • 子类型化关系会导致一系列不太明显的问题。如果您不将自己限制为单一或混合继承,那么您最终会遇到菱形问题。更重要的是您必须处理方差(协变、逆变、不变性),这很快就会变成一场噩梦,尤其是对于类型参数(又名泛型)。还有其他几个原因,即使在 OO 语言中,您也会听到诸如“更喜欢组合而不是继承”之类的说法。
      • 另一方面,如果您简单地省略子类型,您可以对您的类型系统进行更详细的推理,从而可能进行(几乎)完整的类型推断,通常使用 Hindley Milner 类型推断的扩展来实现。

      当然,有时您会错过子类型,但像 Haskell 这样的语言已经找到了解决这个问题的好方法:类型类,它允许为多个类型定义一种通用“接口”(或“通用操作集”)否则不相关的类型。与 OO 语言的不同之处在于类型类可以在“之后”定义,而无需触及原始类型定义。事实证明,你几乎可以用类型类来做任何你可以用子类型做的事情,但是以一种更灵活的方式(并且不会阻止类型推断)。这就是为什么其他语言开始采用类似机制的原因(例如 Scala 中的隐式转换或 C# 和 Java 8 中的扩展方法)

      【讨论】:

        猜你喜欢
        • 2010-09-12
        • 2010-11-04
        • 2010-09-06
        • 2019-11-03
        • 2010-09-06
        • 2012-07-14
        • 2010-11-11
        • 1970-01-01
        相关资源
        最近更新 更多