代码之家  ›  专栏  ›  技术社区  ›  Jon Onstott

函数语言能很好地处理复杂性吗?

  •  6
  • Jon Onstott  · 技术社区  · 16 年前

    我很好奇函数式语言是如何比较(一般)到更大的“传统”语言的,例如大型程序的C语言和Java语言。与使用非功能性语言相比,程序流是否变得更难理解?使用函数式语言编写大型软件项目时,是否需要考虑其他问题或事项?

    谢谢!

    6 回复  |  直到 16 年前
        1
  •  9
  •   Norman Ramsey    16 年前

    与使用非功能性语言相比,程序流是否变得更难理解?

    “程序流”可能是分析大型功能程序的错误概念。控制流可以变成巴洛克式,因为有更高阶的函数,但是这些函数通常很容易理解,因为很少有任何共享的可变状态需要担心,所以您可以只考虑参数和结果。当然,我的经验是,我发现遵循一个积极的功能性程序比一个积极的面向对象程序要容易得多,在这个程序中,实现的一部分被分散在许多类上。我发现使用高阶函数编写的程序比使用动态调度更容易实现。我还观察到,我的学生更能代表整个程序员,他们在继承和动态调度方面都有困难。它们与高阶函数没有类似的困难。

    在写一个大的 使用功能语言的软件项目?

    关键是一个好的模块系统。这是一些评论。

    • 我所知道的最强大的模块系统 unit system of PLT Scheme 由马修·弗拉特和马蒂亚斯·费利森设计。不幸的是,这个非常强大的系统缺少静态类型,这对编程有很大的帮助。

    • 下一个最强大的系统是标准的ml模块系统。不幸的是,标准的ml虽然非常有表现力,但也允许许多有问题的构造,所以业余爱好者很容易把事情弄得一团糟。而且,许多程序员发现很难有效地使用标准的ml模块。

      objective caml模块系统非常相似,但也有一些差异,这些差异有助于减轻标准ml最糟糕的过度使用。语言实际上非常相似,但是objective caml的风格和习惯用法使初学者编写疯狂程序的可能性大大降低。S.

    • 对于功能性语言来说,最不强大/表现力最低的模块系统是haskell模块系统。这个系统有一个严重的缺陷 没有显式接口 因此,拥有模块的大部分认知益处都丧失了。另一个可悲的结果是,尽管haskell模块系统为用户提供了一个层次化的名称空间,但是使用这个名称空间( import qualified ,以防您是内部人员)经常被弃用,许多haskell程序员编写代码时,就好像所有东西都在一个大而平的名称空间中一样。这种做法等于放弃了模块的另一大好处。

    如果我必须用函数式语言编写一个大型系统,并且必须确保其他人理解它,我可能会选择标准的ml,并且我会为模块系统的使用建立非常严格的编程约定。(例如,每个地方都有明确的签名,opague归属于 :> ,而且没有使用 open 对我来说,标准ml核心语言(与ocaml相比)的简单性和标准ml基本库(与ocaml相比)的功能性比ocaml模块系统的优越性更有价值。

    我只做了一个非常大的haskell程序,虽然我发现(并继续发现)在haskell工作非常愉快,但我真的错过了没有显式签名的机会。

    函数语言能很好地处理复杂性吗?

    有些人这样做。我发现ml模块和模块类型(标准的ml和目标的caml)对于管理复杂性、理解复杂性以及在大型程序的不同部分之间放置不可分离的防火墙都是非常有用的工具。我和哈斯凯尔的关系不太好


    最后一点:这些并不是什么新问题。在ada中,将系统分解成由编译器检查的具有单独接口的模块是一个问题, C ,C++,CLU,Muldia-3,我相信很多其他语言。像标准ML或Caml这样的系统的主要好处是获得显式签名和模块化类型检查(C++社区目前正在与模板和概念进行斗争)。我怀疑这些问题是永恒的,对任何大型系统都将是重要的,无论实现语言是什么。

        2
  •  14
  •   Jon Skeet    16 年前

    函数式编程旨在 减少 大型系统的复杂性,通过将每个操作与其他操作隔离开来。当您在没有副作用的情况下编程时,您知道您可以单独查看每个函数-是的,理解一个函数可能也涉及到理解其他函数,但至少您知道它不会干扰其他系统状态。

    当然,这是假设完全纯函数式编程-当然不总是这样。你也可以用功能性的方式使用更传统的语言,尽可能避免副作用。但原则是很重要的:避免副作用会导致更易于维护、理解和测试的代码。

        3
  •  5
  •   Mark Byers    16 年前

    我的看法正好相反。由于没有副作用,用函数式语言编写的程序更容易推理。

        4
  •  0
  •   Thomas Pornin    16 年前

    通常情况下,这不是一个“功能性”与“程序性”的问题;而是一个懒惰的评估问题。

    惰性求值是指您可以在不实际计算值的情况下处理值;相反,该值附加到一个表达式,如果需要,该表达式应该会产生该值。具有延迟计算的语言的主要示例是haskell。懒散的计算允许定义和处理概念上无限的数据结构,所以这很酷,但它也使人类程序员更难在头脑中紧跟在计算机上真正发生的事情的顺序。

    由于历史的原因,大多数语言的惰性评价是“功能性的”。我的意思是这些语言对典型的功能性结构有很好的句法支持。

    没有惰性的计算,函数语言和过程语言允许表达相同的算法,具有相同的复杂性和类似的“可读性”。函数式语言倾向于重视“纯函数”,即没有副作用的函数。纯函数的求值顺序是不相关的:从这个意义上说,纯函数通过简单地标记那些不重要的部分来帮助程序员知道发生了什么。但这是一个间接的好处,纯函数也出现在过程语言中。

        5
  •  0
  •   Hubert    16 年前

    我可以说,函数式语言在处理复杂性方面的主要优势如下:

    1. 函数式编程讨厌副作用。 你真的可以黑盒不同的层 你不会害怕并行处理 ( actor model 就像在erlang中使用起来很容易 而不是锁和线)。
    2. 文化、功能程序员 用于设计DSL来表示 解决一个问题。确定基本要素 问题的原语是 不同于冲着品牌走 新的潮流框架。
    3. 历史上,这一领域一直由非常聪明的人领导: 垃圾收集,面向对象,元编程… 所有这些概念最初都是在功能平台上实现的。 有很多文学作品。

    但这些语言的缺点是缺乏行业内的支持和经验。具有可移植性、性能和互操作性可能是一个真正的挑战,在像Java这样的其他平台上,所有这些似乎都是显而易见的。也就是说,像scala这样基于jvm的语言非常适合从双方受益。

        6
  •  0
  •   C. A. McCann Ravikant Cherukuri    16 年前

    程序流是否变得难以 比 使用非功能性语言?

    在这种情况下,函数式风格鼓励程序员更喜欢抽象的逻辑转换,将输入映射到输出。从“程序流”的角度来思考,假定了一种顺序的、有状态的操作模式——虽然功能性程序可能在“引擎盖”下有顺序状态,但它通常不是围绕着这一点来构建的。

    通过比较“处理数据集合”的命令式方法和功能性方法,可以很容易看出视角上的差异。前者倾向于使用结构化迭代,比如 for while 循环,告诉程序“执行此任务序列,然后移动到下一个并重复,直到完成”。后者倾向于使用抽象递归,比如 fold map 函数,告诉程序“这里有一个组合/转换元素的函数——现在使用它”。不必通过如下函数遵循递归程序流 地图 ;因为它是无状态的抽象,所以只需考虑它的含义,而不是它在做什么。

    这也许有点告诉我们,函数式方法已经慢慢地渗透到了非函数式语言中 foreach 循环,python的列表理解…

    推荐文章