【问题标题】:immutability of data structures and variables in functional programming函数式编程中数据结构和变量的不变性
【发布时间】:2017-01-16 20:42:00
【问题描述】:

通常说在函数式编程中数据结构是不可变的。我知道不可变数据结构是一种无法更改的数据结构。

但是,这是否也意味着变量引用也不能更改?

例如,

var arr = [1,2,3]

arr = [4,5,6]

在这段代码中,我没有更改数组 [1,2,3],而是创建了一个新数组。尽管如此,我还是更改了变量“arr”的引用。这段代码是否遵循不可变数据结构的原则?

【问题讨论】:

    标签: functional-programming immutability


    【解决方案1】:

    是不是也意味着变量引用也不能改变?

    是的。它们被称为常量。你最好写

    const arr1 = [1,2,3] 
    const arr2 = [4,5,6]
    

    这种方法也允许您将作用域环境视为不可变的数据结构,这应该是默认值。它使您的代码的推理变得更加容易。

    【讨论】:

      【解决方案2】:

      您不应重新分配引用。理想情况下,您会创建一个新变量,这样您就可以看到您所做的任何更改的“之前和之后”。

      但是,即使指向它的引用发生了变化,底层结构仍然可以是不可变的。如果有人正在查看旧版本的结构,重新分配引用不会损害数据的有效性,因为旧版本仍然存在,没有改变。

      【讨论】:

      • 如果一个数据结构是可变的,那么一旦一个线程修改它并且另一个线程读取它,就必须做一些工作来防止竞争条件。不可变数据结构节省了处理竞争条件的工作量。但是,不可变引用有什么好处?为什么函数式编程更改引用不好?
      • @CrazySynthax 因为它使思考代码和在没有任何变化时遵循“数据流”变得更加容易。假设您有一个大型函数,其中始终使用某个变量。如果该变量在函数的中途有条件地重新分配,那么现在您必须考虑之前的值是什么,它变成了什么,而不是仅仅知道该值保持不变。
      • @CrazySynthax 在函数式编程中,与命令式编程不同,重新分配不是必需的,而且由于除了不创建更多变量之外没有任何好处,所以不应该这样做。
      • 是的,这就是我要说的。这在命令式编程中是必要的,因为该范例严重依赖于需要重新分配引用的循环构造。在标准命令式for-loop 中,由于循环本身不会评估为值,因此您需要重新分配现有引用才能看到循环的效果(或以其他方式执行副作用)。在函数式编程中,您将使用 reduce 或 map 来代替,它会创建新变量而不是修改现有变量。
      • @CrazySynthax 我应该澄清一下,分配是否是线程安全的取决于语言等。使用不可变数据结构时,任何给定线程都将查看值的不可变副本,而不是引用。当您将arr 重新分配给第二个数组时,这不会产生任何影响,因为查看原始数组的任何人都将持有原始数组的副本;他们不依赖参考。
      猜你喜欢
      • 1970-01-01
      • 2021-05-26
      • 2018-07-16
      • 2023-04-02
      • 1970-01-01
      • 2019-08-21
      • 2016-04-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多