有人可以向我解释为什么我需要函数式编程而不是OOP吗?

Can someone explain to me why I would need functional programming instead of OOP?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Functional programming vs Object Oriented programming

有人能告诉我为什么我需要函数式编程而不是OOP吗?

为什么我需要使用Haskell而不是C++(或者类似的语言)?

与OOP相比,函数式编程的优势是什么?


one of the大事情可能在缺乏功能的"幽灵programming is the action at a的距离。"你是什么,你得到与EEA和不涵盖更多。这将使代码easier about to reason。P></

让我们用简单的实例。让我们说如何在Java代码片段中的无论哪种茶X = 10二郎(OOP)RR(函数)。我知道这些事情在Erlang非常快:P></

  • Xthe variable is in the context在我眼前。周期。或者是在passed to the function参数在阅读或是我被分配第一(the only & & mdash;c.f. below)时间。
  • Xhas the value of variable from this onward 10点。它将not change of block了我在阅读队列。恩我。
  • 在Java很复杂:黑莓P></

  • 定义变量Xthe might be as a参数。
  • ?可能在其他地方定义的方法。
  • ?可能定义的部分是在the method of the class。
  • 无论是因为我的茶馆,在这里我不declaring EN,changing its value。我不知道this means the value of Xwill be without the队列扫描后一constantly to find the last广场外面或修饰(或指定explicitly implicitly类在for循环)。
  • 当呼叫Xanother method,to be a级,如果发生超时变量可以改变从它下面我用我不知道this Way for the method of that没有inspecting队列。
  • in the context of a线程程序它甚至更糟。Xcan be changed by something甚至不能看到我眼前的环境。另一个线程在# may be that the method呼叫modifies X5。
  • 和Java语言面向对象的relatively是无知的。the number of that can be screwed X方式与C + +是在高和potentially不明甚至更多。P></

    and the thing is?example of this is just a simple operation can be普通知识,让更多的OOP在安(或其他复杂的强制性)比在语言功能。EN address of the利益也不T功能编程,不交mutable,等.高阶函数的类。P></


    哈斯克尔有三件事我觉得很酷:好的。

    1)它是一种静态类型的语言,非常有表现力,允许您快速构建高度可维护和可重构的代码。在静态类型语言如Java和C语言以及Python和Ruby之类的动态语言之间一直存在着很大的争论。Python和Ruby使您可以快速构建程序,只使用Java或C语言所需的行数的一部分。因此,如果您的目标是快速进入市场,那么python和ruby是不错的选择。但是,因为它们是动态的,重构和维护代码是很困难的。在Java中,如果要向方法添加参数,则很容易使用IDE来查找方法的所有实例并修复它们。如果你错过了一个,编译器就会抓住它。使用python和ruby,重构错误只会被捕获为运行时错误。因此,对于传统语言,一方面可以在快速开发和糟糕的可维护性之间进行选择,另一方面可以在缓慢开发和良好的可维护性之间进行选择。两种选择都不是很好。好的。

    但是有了哈斯克尔,你不必做出这种选择。Haskell是静态类型的,就像Java和C.*一样。因此,您可以获得所有的可重构性、潜在的IDE支持和编译时检查。但同时,编译器可以推断类型。所以,它们不会像处理传统静态语言那样妨碍您的工作。此外,该语言还提供了许多其他特性,使您只需几行代码就可以完成很多工作。因此,您可以得到Python和Ruby的开发速度以及静态语言的安全性。好的。

    2)平行度。因为函数没有副作用,所以编译器可以更容易地并行运行,而不需要开发人员做太多的工作。考虑以下伪代码:好的。

    1
    2
    3
    a = f x
    b = g y
    c = h a b

    在纯函数语言中,我们知道函数f和g没有副作用。所以,没有理由在g之前运行f。可以交换订单,或者同时运行它们。实际上,在函数h中需要f和g的值之前,我们根本不需要运行f和g。在传统语言中,这是不正确的,因为对f和g的调用可能会产生副作用,需要我们以特定的顺序运行它们。好的。

    随着计算机上越来越多的内核,函数式编程变得越来越重要,因为它允许程序员轻松地利用可用的并行性。好的。

    3)关于haskell的最后一件很酷的事情可能也是最微妙的:懒惰的评估。要理解这一点,可以考虑编写一个程序来读取文本文件并打印出文件每行中出现"the"一词的次数。假设您使用的是传统的命令式语言。好的。

    尝试1:编写一个函数,打开文件并一次读取一行。对于每一行,计算"the"的数目,然后打印出来。这很好,除了您的主逻辑(计算单词)与您的输入和输出紧密耦合。假设您想在其他上下文中使用相同的逻辑?假设您想从一个套接字中读取文本数据并计算单词数?或者您想从用户界面读取文本?你必须重新改写你的逻辑!好的。

    最糟糕的是,如果你想为你的新代码编写一个自动测试怎么办?您必须构建输入文件、运行代码、捕获输出,然后将输出与预期结果进行比较。这是可行的,但很痛苦。通常,当IO与逻辑紧密结合时,测试逻辑会变得非常困难。好的。

    尝试2:那么,让我们分离IO和逻辑。首先,将整个文件读取到内存中的一个大字符串中。然后,将字符串传递给一个将字符串拆分为行的函数,计算每行的"s",并返回一个计数列表。最后,程序可以循环计数并输出它们。现在很容易测试核心逻辑,因为它不涉及IO。现在很容易将核心逻辑与来自文件、套接字或UI的数据一起使用。所以,这是一个很好的解决方案,对吧?好的。

    错了。如果有人传入100GB文件怎么办?因为整个文件必须加载到一个字符串中,所以您将耗尽内存。好的。

    尝试3:围绕读取文件和生成结果构建一个抽象。您可以将这些抽象看作两个接口。第一个方法有nextline()和done()。第二个具有outputCount()。您的主程序实现nextline()和done()从文件中读取,而outputcount()直接打印出计数。这允许主程序在恒定内存中运行。您的测试程序可以使用这个抽象的另一个实现,这个抽象有nextline()和done()从内存中提取测试数据,而outputcount()检查结果而不是输出结果。好的。

    第三次尝试很好地分离了逻辑和IO,它允许程序在恒定内存中运行。但是,这比前两次尝试要复杂得多。好的。

    简而言之,传统的命令式语言(无论是静态的还是动态的)常常让开发人员在好的。

    a)IO与逻辑的紧密耦合(难以测试和重用)好的。

    b)将所有内容加载到内存中(效率不高)好的。

    c)构建抽象(复杂,并且会减慢实现速度)好的。

    当读取文件、查询数据库、读取套接字等时,就会出现这些选择。程序员似乎更喜欢选项A,因此单元测试也会受到影响。好的。

    那么,哈斯克尔对此有何帮助?在Haskell中,您可以像尝试2中一样解决这个问题。主程序将整个文件加载到一个字符串中。然后它调用一个函数来检查字符串并返回一个计数列表。然后主程序打印计数。测试和重用核心逻辑非常容易,因为它与IO隔离。好的。

    但是内存使用情况呢?哈斯凯尔懒惰的评价会帮你解决这个问题。因此,即使您的代码看起来像是将整个文件内容加载到一个字符串变量中,但实际上并没有加载整个内容。相反,只在使用字符串时读取文件。这允许一次读取一个缓冲区,实际上您的程序将在恒定内存中运行。也就是说,您可以在100GB文件上运行这个程序,它将消耗很少的内存。好的。

    类似地,您可以查询数据库,构建包含大量行的结果列表,并将其传递给函数进行处理。处理函数不知道行来自数据库。所以,它与IO是分离的。并且在封面下,行列表将被懒惰而有效地获取。所以,即使当您查看代码时看起来像这样,完整的行列表永远不会同时全部在内存中。好的。

    最终结果是,您可以测试处理数据库行的函数,而不必连接到数据库。好的。

    懒惰的评价真的很微妙,需要一段时间才能让你的头脑清醒过来。但是,它允许您编写易于测试和重用的简单代码。好的。

    这里是最后的Haskell解决方案和方法3 Java解决方案。两者都使用恒定内存,并将IO与处理分离,以便测试和重用。好的。

    Haskell:好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    module Main
        where

    import System.Environment (getArgs)
    import Data.Char (toLower)

    main = do
      (fileName : _) <- getArgs
      fileContents <- readFile fileName
      mapM_ (putStrLn . show) $ getWordCounts fileContents

    getWordCounts = (map countThe) . lines . map toLower
        where countThe = length . filter (=="the") . words

    爪哇:好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileReader;
    import java.io.Reader;

    class CountWords {
        public interface OutputHandler {
            void handle(int count) throws Exception;
        }

        static public void main(String[] args) throws Exception {
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(new FileReader(new File(args[0])));

                OutputHandler handler = new OutputHandler() {
                    public void handle(int count) throws Exception {
                        System.out.println(count);
                    }
                };

                countThe(reader, handler);
            } finally {
                if (reader != null) reader.close();
            }
        }

        static public void countThe(BufferedReader reader, OutputHandler handler) throws Exception {
            String line;
            while ((line = reader.readLine()) != null) {
                int num = 0;
                for (String word: line.toLowerCase().split("([.,!?:;'"-]|\\s)+")) {
                    if (word.equals("the")) {
                        num += 1;
                    }
                }
                handler.handle(num);
            }
        }
    }

    好啊。


    如果我们出现Haskell语言和C + +的功能,使调试非常容易,因为没有被发现的类和变量mutable酮C、Python等。which should你永远亲爱的一切,和它ensured Arguments given some that,总是会返回,函数结果尽管the same the number of时报评价你的恩。P></

    面向对象的编程范式是正交to any,which there are lanugages和FP与面向对象的组合,是最流行的ocaml implementations Haskell,several等。P></