Baj*_*k80 4 c# oop erlang functional-programming scala
最近我一直在学习在Erlang中作为C和C#开发人员的长期编程.我对函数式编程很新.现在,我试图了解Scala等语言中的对象是如何工作的.我被告知OOP是关于使用其公共方法改变给定对象的状态.这些方法改变了公共财产和私人成员的状态.但现在我听说在函数式编程中,所有对象都应该是不可变的.好吧,我同意,一旦赋值变量(在给定函数中)应该保持指向同一个对象.但这种"不变性"是否意味着我无法使用公共方法更改给定对象的内部(属性,私有成员)?这使对象就像简单的数据容器一样.它提取了它们之外的所有功能.这使得对象更像C中的结构.这对我来说很奇怪.也许我错过了什么?是否有可能以旧式方式使用对象并仍将其视为函数式编程?
OOP 就是使用其公共方法更改给定对象的状态。
这是一个谎言!
在函数式编程中,所有对象都应该是不可变的
这是一个谎言!
但是这种“不变性”是否意味着我不能使用它们的公共方法更改给定对象的内部(属性、私有成员)?
有严格的不变性和“模拟”不变性。通过“模拟”不变性,您可以更改内部结构,但不应产生可见的更改。例如,大量计算的缓存仍然是可以接受的。
是否有可能以老式的方式使用对象并仍然将其视为函数式编程?
这取决于您如何准确地改变对象以及您如何定义 FP。实际上,该死的,你可以在 FP 中改变对象。
也许我错过了什么?
是的,有很多东西你应该学习。
关于不可变对象,您不了解以下几点:
以下是您应该了解的有关 OOP 的内容:
以下是您应该了解的关于 FP 的事情:
FP 不要求您使用不可变数据。但是在 FP 中处理不可变数据要容易得多。
如果一棵树倒在树林里,它会发出声音吗?如果一个纯函数为了产生一个不可变的返回值而改变一些本地数据,这样可以吗?”
好的 FP 语言有很多方法来处理可变数据以满足性能需求。FP 只是喜欢隐藏突变。
只有纯 FP 语言迫使您使用不可变数据。
FP 因其作为一等公民的功能而得名。在wiki上查看更多信息。您可以像使用 & 传递对象一样使用 & 传递函数。
好吧,很多 FP 与函数无关。
您还应该知道 OOP 和 FP 的关系:
现在,我想解释一下为什么有很多人认为某些范式不能组合:
澄清一下:FP 风格的创造者不是白痴。他们希望副作用是明确的和可控的。所以有一个很好的概念:纯函数。
总结:
你混合了三个不同的概念.函数式编程,可变性和OOP是三个不同的东西.
我被告知OOP是关于使用其公共方法改变给定对象的状态.
是的,不是.O OP中最重要的是你有对象,可以同时携带数据和代码(它们的成员方法),并且你可以使用它们的界面与对象交谈,这样对象就可以了
this在方法实现中访问)没有人规定你这个方法调用做了什么,或者它必须修改一些状态.
碰巧是OOP在与州合作时有助于恢复一些基本的理智.这是因为应用程序的可怕的复杂全局状态可以被切割成更小的部分并隐藏在可变对象中.此外,这些可变对象还可以通过禁止直接访问其状态并仅提供可以修改该状态的一组受限操作来尝试维护至少一些本地不变量.
但现在我听说在函数式编程中,所有对象都应该是不可变的.
他们应该尊重参考透明度.如果您的对象没有可变状态且只有方法没有任何副作用,那么它就足以引用透明度.足够但不必要:对象可以具有更复杂的内部结构,但从外部看起来完全不可变.缓存就是一个很好的例子.
此外,即使是纯函数式程序也不仅限于使用不可变数据结构.有纯粹的可变状态这样的东西.我们的想法是,您的功能程序用于构建类似于处理可变状态的复杂行动计划.该计划本身是一个不可变的实体.这个计划可能非常复杂,但由于它是由纯函数构建的,因此它仍然可以很容易地推理出来.该计划仅使用纯函数构建,然后可以提供给一个小而简单的解释器,该解释器在可变内存上执行计划.通过这种方式,您可以获得两个世界的好处:在构建计划时,您具有纯函数的概念简单性,但是当您在可变数据结构上执行此计划时,您还具有接近金属计算的性能.
但这种"不变性"是否意味着我无法使用公共方法更改给定对象的内部(属性,私有成员)?
一般来说,是的.但是,在Scala中,默认情况下不会强制执行不变性.您可以决定应用程序的哪些部分足够复杂,因此将自己限制为纯函数可能是值得的.如果这更容易,其他所有东西都可以使用普通的可变结构来实现.
这使对象就像简单的数据容器一样.它提取了它们之外的所有功能.
不,因为对象仍然随身携带虚拟调度表.然后,您可以从外部请求对象调用该方法apply(integer i),并且该对象(取决于它的对象类型)可能会调用完全不同的东西,例如
/** get i-th character */
String.apply(integer i)
Run Code Online (Sandbox Code Playgroud)
要么
/** get value for key `i` */
TreeMap.apply(integer i)
Run Code Online (Sandbox Code Playgroud)
如果C没有基本上重新实现子类多态作为设计模式,则不能使用结构.
是否有可能以旧式方式使用对象并仍将其视为函数式编程?
这不是一个全有或全无的游戏.你可以从经典的oop语言开始(具有可变状态和所有这些),它在某种程度上支持函数式编程范例.然后,您可以查看您的应用程序,并隔离它需要更精确控制副作用的那些方面.您必须确定哪些副作用很重要,哪些不太重要.然后你可以使用更纯粹的函数来表达真正关键的部分(纯粹的意义:纯粹的你需要它们,即不执行任何关键的副作用而不在其签名中明确声明它).结果将是在一个应用程序中混合使用经典OOP和FP.
使用纯函数编写程序可以被认为是在某种原始逻辑中构造证明.如果你能在需要的时候做到这一点很好(使用更严格的纯函数方法),但是如果你不需要它就可以省略它(使用通常的方法,带有杂乱的副作用函数) ).