学习一种功能语言是否会使一个更好的OOP程序员变得更好?[关闭]


28

作为Java / C#/ C ++程序员,我听到了很多关于函数式语言的讨论,但从未发现有必要学习一种。我还听说过,功能语言中引入的更高层次的思维使您成为更好的OOP /过程语言程序员。

有人可以确认吗?它以什么方式提高了您的编程技能?

为了提高不那么复杂的语言的技能,学习语言的最佳选择是什么?


3
如果您使用C#进行编码,那么您已经知道了。LINQ是相当实用的东西。
SK-logic

我认为OOP更适合对现实生活的对象进行建模。
图兰斯·科尔多瓦

1
@ user61852大多数OO设计模式不对“现实生活”对象建模,而实际上对高度抽象的概念建模。
Andres F.

不仅仅是Java / C#(+ C ++)程序员。巨大的瑞士军刀和一个不太小的小册子之间有一个区别,该小册子概述了为什么您会从40个刀片中选择X刀片,并且您可以在您喜欢的任何物体上刻出该死的刀片,因为它既锋利又弯曲正确,这样您就可以将其强大的切割功能应用于多种情况,而无需多加考虑。(当然还有开瓶器)
Erik Reppen

Answers:


32

基本上同意FrustratedWithFormsDesign的回答,但您也询问如何学习新的范式有助于提高自己的技能。我可以根据自己的经验举几个例子。

自从学习函数式编程以来,我更加意识到与我一起使用的概念更自然地被视为“对象”(通常在有意义的情况下被视为对象),而更自然地被视为不可变的“值”(我认为有一个重要区别,探讨OO的意义与FP的意义,但这只是我的看法。

我注意到我的代码在哪些地方包含副作用,因此我更加谨慎地将那些地方隔离开来,使我的函数成为“纯”函数。这大大提高了我的OO代码的可测试性。

我对数据表示中的周期更加了解。(例如,我认为您无法在Haskell中编写函数将链表转换为双链表,因此您会注意到该语言的循环更多。)避免循环会减少同步量您需要使数据结构在内部保持一致,从而减轻线程之间共享这些结构的负担。

我更可能依赖于递归(方案的递归循环结构很漂亮)。Dijkstra在《结构化编程说明》中谈到了这一点的重要性-递归算法非常直接地映射到数学归纳法,他建议这是从智力上证明我们的循环正确的唯一方法。(我不建议我们必须证明我们的代码正确,但我们越容易使自己做到这一点,我们的代码就越有可能是正确的。)

我更有可能使用高阶函数。约翰·休斯(John Hughes)的论文《函数编程为何如此重要》。它强调了采用函数式编程技术所具有的可组合性,其中高阶函数起着主要作用。

同样,正如Jetti的回答中所提到的那样,您会发现许多FP想法已被合并到较新的OO语言中。Ruby和Python都提供许多高阶函数,我听说LINQ被描述为试图将对Monadic理解的支持引入C#,甚至C ++现在都具有lambda表达式。


@Aidan:C ++ 0x中的wrt lambdas,无论如何,新的C ++编译器已经将它们合并了。
Matthieu M.

1
作为“保持可变状态的事物”的“对象”非常普遍,但是“价值对象”模式已经存在了很多年。
Frank Shearar'2

@Matthieu,谢谢,我已经更新了文字以反映这一点。
艾丹·库利(Aidan Cully)

@弗兰克:谢谢你的指导。我没有在答案中包含此内容,但是我必须将“值转换为对象”的主要反对意见与区别b / w对象接口(由对象拥有)和操作(其中对象之间的关系更多)有关比对象本身更重要)。 1 + 2在数学上等价于2 + 1,但1.+(2)在实现上与2.+(1)。使用操作比使用对象接口更自然地理解存在许多SW问题。
艾丹·库利(Aidan Cully)

1
@Aidan您是否读过William Cook的“重新理解数据抽象”?它探究了对象和ADT之间的差异,这正是您所暗示的。
Frank Shearar 2011年

32

我不会说这是保证让你更好的OOP程序员,但它会向你介绍一种新的思维方式,而可以让你更好的解决问题的一般,不只是在OOP方面。


3
鉴于对象实际上是高阶函数,我发现学习FP知识确实对我的OOP有帮助。正如您所说,它更普遍地适用/有用。
Frank Shearar'2

12

学习功能语言-对我来说Lisp-在构建并行应用程序时确实很有帮助。功能方法(基于状态,无副作用)更容易同步,并且更容易使线程安全,因为它们仅依赖于其输入。这意味着您需要监视给定代码区域的唯一数据是您传入的参数。这也使调试更加容易。


您会发现它对线程库也有帮助,线程库倾向于将纯函数作为其任务。它还可以间接地帮助您,在某些地方,我将以一种“功能样式”编写OO代码,其中存在一个“拥有参数”,该所有权参数隐式锁定了它所引用并由该函数使用的一堆对象。 。只要记录您的期望(并对其进行单元测试),就可以为您提供更好的多线程代码,并且锁定问题很少。很少有显式锁。

我从未听说过Prolog被称为功能语言。如果我斜视一下,我可以隐约地看到Prolog(的一部分)可以如何帮助FP。
2011年

1
Prolog不是功能性语言。这是一种逻辑语言。如果你想有一个Prolog- 逻辑语言的综合函数式编程为好,头脑,你可以抢在甘德水星。警告:即使您已经了解Prolog,也会对您的大脑造成一点伤害。
我的正确观点,

@正确的观点:是的,我认为你是对的。猜猜我需要学习更多有关函数式语言的知识!
Michael

1
@moz:是的,我希望Java有lambda。匿名Thread对象...笨拙。
Michael K

9

学习任何其他编程范例都会提高您的编程技能。当编程不是学术研究级的东西时(甚至经常如此),它基本上是解决问题的方法。一句话思考。各种范例是思考问题及其解决方案的不同方式。因此,不要仅仅将其视为“学习功能语言”。可以将其视为“学习思考问题及其解决方案的另一种方式”。然后,即使您从未真正使用过语言,也会看到学习语言的好处。

为了解决您的特定问题,我曾经是一名C ++程序员,那是在过去的日子里(在没有C ++标准之前)。我遵循所有常用的东西,并持有通过方法等等操作状态的对象。然后我偶然发现了Haskell并了解了其中的大部分内容。(我认为从来没有人真正地学习过Haskell。)在我的一位同事,即分配给我小组的测试人员,随手评论说我的代码变得更容易测试之前,这项练习似乎有些浪费。

发生的事情是,我开始使我的对象变得越来越不可改变。具有复杂可变状态的类开始被替换为通过更改克隆自身并返回新对象的类。共享对象开始被具有写时复制语义的对象所取代(因此给人以很多对象克隆的错觉,而没有内存开销)。除非绝对必要,否则功能没有副作用。“功能”的纯数学定义越来越普遍。当我探索越来越多的函数式编程空间时,所有这些自然就开始在我的代码中发生-没有意识的参与。

现在,我的目标是每两年学习至少一个新的编程范例(即使它只是像AOP这样的次要扩展范例),并且每个范例中至少要包含两种新语言(一种尽可能纯净,一种混合​​/实用) )。每个人都给了我新的智力工具,可以用任何语言将其应用于我的所有编程,因此,我认为花费在学习它们上的时间并没有浪费多少。


3

我之前已经说过,我会再说一遍,学习功能语言肯定可以改善我的C#。它帮助我理解了lambda(并帮助我爱上了它们)。这也使我意识到在使用异步操作时,我更喜欢函数式编程(F#)!


3

机器代码不过是一系列副作用-处理器直接执行的命令。C语言的副作用是不同的,而不是处理寄存器和物理硬件,而是处理一组抽象,然后让编译器完成所有脏活。C还使您可以在循环和if语句中构造副作用。C ++通过向语言添加OOP和一些急需的功能对C进行了改进。Java和C#添加垃圾回收,Python添加动态类型。

即使具有所有这些功能-这些语言的动态键入,垃圾回收等程序仍完全基于副作用。功能编程语言(例如Scheme,Clojure,Haskell和ML)完全不同,这些语言更接近于数学,而更接近于机器代码。而不是使用副作用,而是在函数周围传递值。

为了提高不那么复杂的语言的技能,学习语言的最佳选择是什么?

我建议Scheme,它是最小的,它已在MIT的旧入门编程类中使用。其他函数式编程语言很难学习。Clojure带来了Java的所有复杂性,ML带来了复杂的静态类型系统,Haskell有时被称为学术语言-对于初学者来说并不理想,等等。另一方面,方案很容易学习和理解。

它以什么方式提高了您的编程技能?

几乎所有高级编程语言都具有函数和递归-函数式编程所基于的概念。因此,您对FP的了解几乎在所有地方都应该有所帮助,但是,如果您真的想进行功能编程,则应该使用一种自然而高效的语言,而不是尝试根据自己的喜好来弯曲别人的语言设计,也就是说您应该使用函数式编程语言来进行函数式编程。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.