gpt4 book ai didi

c# - 函数式编程中的对象 - 不变性

转载 作者:太空狗 更新时间:2023-10-30 00:29:45 32 4
gpt4 key购买 nike

最近,作为 C 和 C# 开发人员,我一直在学习用 Erlang 编程。我对函数式编程相当陌生。现在,我试图了解 Scala 等语言中的对象是如何工作的。我被告知 OOP 就是使用其公共(public)方法更改给定对象的状态。这些方法改变公共(public)属性和私有(private)成员的状态。但是现在我听说在函数式编程中所有对象都应该是不可变的。好吧,我同意一旦分配变量(在给定函数中)应该保持指向同一个对象。但是这种“不变性”是否意味着我不能使用它们的公共(public)方法更改给定对象的内部(属性、私有(private)成员)?这使得对象就像简单的数据容器。它提取了它们之外的所有功能。这使得对象的行为更像 C 中的结构。这对我来说很奇怪。也许我错过了什么?是否有可能以老式的方式使用对象并仍然将其视为函数式编程?

最佳答案

你混淆了三个不同的概念。函数式编程、可变性和 OOP 是三个不同的东西。

I have been taught that OOP is all about changing state of given object using its public methods.



是和否。重要事项 Ø OP 是你有对象,它们可以同时携带数据和代码(它们的成员方法),并且你使用它们的接口(interface)与对象交谈,这样对象就可以
  • 调度到被调用方法的具体实现
  • 提供存储在对象携带的数据中的附加信息(在方法实现中访问 this)
  • 执行方法实现的代码

  • 没有人规定你这个方法调用做什么,或者它必须修改一些状态。

    碰巧的是,在处理状态时,OOP 有助于恢复一些基本的理智。这是因为应用程序极其复杂的全局状态可以被分割成更小的部分并隐藏在可变对象中。此外,这些可变对象还可以通过禁止直接访问其状态并仅提供一组可以修改该状态的受限操作来尝试维护至少一些局部不变量。

    But now I hear that in functional programming all objects should be immutable.



    他们应该尊重引用透明度。如果你的对象没有可变状态,只有没有任何副作用的方法,那么引用透明就足够了。足够,但不是必需的:对象可以具有更复杂的内部结构,但从外部看起来完全不可变。缓存就是一个很好的例子。

    此外,即使是纯函数式程序也不仅限于使用不可变数据结构。有纯可变状态这样的东西。这个想法是你的函数式程序被用来构建处理可变状态的复杂 Action 计划之类的东西。计划本身是一个不可变的实体。这个计划可能非常复杂,但由于它是由纯函数构建的,因此它仍然很容易推理。这个仅使用纯函数构建的计划然后可以提供给一个小而简单的解释器,它在可变内存上执行该计划。通过这种方式,您可以获得两全其美的好处:在构建计划时,您拥有纯函数在概念上的简单性,但是当您在可变数据结构上执行此计划时,您还拥有接近金属计算的性能.

    But does this "immutability" mean that I cannot change the internals (properties, private members) of given objects using their public methods?



    一般来说,是的。但是,在 Scala 中,默认情况下不强制执行不变性。您可以决定应用程序的哪些部分足够复杂以进行推理,因此将自己限制为纯函数可能是值得的。其他一切都可以使用普通的可变结构来实现,如果这更容易的话。

    This makes objects just like simple data containers. It extracts all of the functionality outside of them.



    不,因为对象仍然带有它们的虚拟调度表。然后,您可以要求外部对象调用方法 apply(integer i) ,并且对象,取决于它是什么类型的对象,然后可能会调用完全不同的东西,比如
    /** get i-th character */ 
    String.apply(integer i)

    或者
    /** get value for key `i` */ 
    TreeMap.apply(integer i)

    你不能用 C 做到这一点结构,而无需将子类多态性重新实现为设计模式。

    Is it possible to use objects the old-fashioned-way and still consider it as functional programming?



    这不是一个全有或全无的游戏。您可以从经典的 oop 语言(具有可变状态和所有这些)开始,它在某种程度上支持函数式编程范式。然后,您可以查看您的应用程序,并隔离需要更精确控制副作用的那些方面。您必须决定哪些副作用很重要,哪些不太重要。然后,您可以使用更严格的纯函数方法来表达真正关键的部分(在某种意义上是纯函数:如您所需要的那样纯,即不执行任何关键的副作用,而无需在其签名中明确声明)。结果将是在一个应用程序中混合使用经典的 OOP 和 FP。

    使用纯函数编写程序可以被认为是在某种原始逻辑中构造证明。如果您可以在需要时使用它(对纯函数使用更严格的方法),那很好,但是如果您可以在不需要时省略它(使用带有杂乱副作用函数的常用方法),那也很好)。

    关于c# - 函数式编程中的对象 - 不变性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48650381/

    32 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com