zoukankan      html  css  js  c++  java
  • 函数式编程概述

    函数式编程概述

    “函数式编程”, 又称泛函编程, 是一种”编程范式”(programming paradigm),也就是如何编写程序的方法论。它的基础是 λ 演算(lambda calculus)。λ演算可以接受函数当作输入(参数)和输出(返回值)。

    和指令式编程相比,函数式编程的思维方式更加注重函数的计算。它的主要思想是把问题的解决方案写成一系列嵌套的函数调用。

    函数式编程中最古老的例子莫过于1958年被创造出来的Lisp了。Lisp由约翰·麦卡锡(John McCarthy,1927-2011)在1958年基于λ演算所创造,采用抽象数据列表与递归作符号演算来衍生人工智能。较现代的例子包括Haskell、ML、Erlang等。现代的编程语言对函数式编程都做了不同程度的支持,例如:JavaScript, Coffee Script,PHP,Perl,Python, Ruby, C# , Java 等等(这将是一个不断增长的列表)。

    函数式编程思想是一个非常古老的思想。简述如下:

    • 我们就从1900 年 David Hilbert 的第 10 问题(能否通过有限步骤来判定不定方程是否存在有理整数解?) 开始说起吧。

    • 1920,Schönfinkel,组合子逻辑(combinatory logic)。直到 Curry Haskell 1927 在普林斯顿大学当讲师时重新发现了 Moses Schönfinkel 关于组合子逻辑的成果。Moses Schönfinkel的成果预言了很多 Curry 在做的研究,于是他就跑去哥廷根大学与熟悉Moses Schönfinkel工作的Heinrich Behmann、Paul Bernays两人一起工作,并于 1930 年以一篇组合子逻辑的论文拿到了博士学位。Curry Brooks Haskell 整个职业生涯都在研究组合子,实际开创了这个研究领域,λ演算中用单参数函数来表示多个参数函数的方法被称为 Currying (柯里化),虽然 Curry 同学多次指出这个其实是 Schönfinkel 已经搞出来的,不过其他人都是因为他用了才知道,所以这名字就这定下来了;并且有三门编程语言以他的名字命名,分别是:Curry, Brooks, Haskell。Curry 在 1928 开始开发类型系统,他搞的是基于组合子的 polymorphic,Church 则建立了基于函数的简单类型系统。

    • 1929, 哥德尔(Kurt Gödel )完备性定理。Gödel 首先证明了一个形式系统中的所有公式都可以表示为自然数,并可以从一自然数反过来得出相应的公式。这对于今天的程序员都来说,数字编码、程序即数据计算机原理最核心、最基本的常识,在那个时代却脑洞大开的创见。

    • 1933,λ 演算。 Church 在 1933 年搞出来一套以纯λ演算为基础的逻辑,以期对数学进行形式化描述。 λ 演算和递归函数理论就是函数式编程的基础。

    • 1936,确定性问题(decision problem,德文 Entscheidungsproblem (发音 [ɛntˈʃaɪ̯dʊŋspʁoˌbleːm])。 Alan Turing 和 Alonzo Church,两人在同在1936年独立给出了否定答案。

    1935-1936这个时间段上,我们有了三个有效计算模型:通用图灵机、通用递归函数、λ可定义。Rosser 1939 年正式确认这三个模型是等效的。

    • 1953-1957,FORTRAN (FORmula TRANslating ),John Backus。1952 年 Halcombe Laning 提出了直接输入数学公式的设想,并制作了 GEORGE编译器演示该想法。受这个想法启发,1953 年 IBM 的 John Backus 团队给 IBM 704 主机研发数学公式翻译系统。第一个 FORTRAN (FORmula TRANslating 的缩写)编译器 1957.4 正式发行。FORTRAN 程序的代码行数比汇编少20倍。FORTRAN 的成功,让很多人认识到直接把代数公式输入进电脑是可行的,并开始渴望能用某种形式语言直接把自己的研究内容输入到电脑里进行运算。John Backus 在1970年代搞了 FP 语言,1977 年发表。虽然这门语言并不是最早的函数式编程语言,但他是 Functional Programming 这个词儿的创造者, 1977 年他的图灵奖演讲题为[“Can Programming Be Liberated From the von Neumann Style? A Functional Style and its Algebra of Programs”]

    • 1956, LISP, John McCarthy。John McCarthy 1956年在 Dartmouth一台 IBM 704 上搞人工智能研究时,就想到要一个代数列表处理(algebraic list processing)语言。他的项目需要用某种形式语言来编写语句,以记录关于世界的信息,而他感觉列表结构这种形式挺合适,既方便编写,也方便推演。于是就创造了LISP。正因为是在 IBM 704 上开搞的,所以 LISP 的表处理函数才会有奇葩的名字: car/cdr 什么的。其实是取 IBM704 机器字的不同部分,c=content of,r=register number, a=address part, d=decrement part 。

    面向函数编程(FOP)

    在FP中,一切皆是函数。

    函数式编程(FP)是关于不变性和函数组合的一种编程范式。

    函数式编程语言实现重用的思路很不一样。函数式语言提倡在有限的几种关键数据结构(如list、set、map)上 , 运用函数的组合 ( 高阶函数) 操作,自底向上地来构建世界。

    当然,我们在工程实践中,是不能极端地追求纯函数式的编程的。一个简单的原因就是:性能和效率。例如:对于有状态的操作,命令式操作通常会比声明式操作更有效率。纯函数式编程是解决某些问题的伟大工具,但是在另外的一些问题场景中,并不适用。因为副作用总是真实存在。

    OOP喜欢自顶向下架构层层分解(解构),FP喜欢自底向上层层组合(复合)。 而实际上,编程的本质就是次化分解与复合的过程。通过这样的过程,创造一个美妙的逻辑之塔世界。

    我们经常说一些代码片段是优雅的或美观的,实际上意味着它们更容易被人类有限的思维所处理。

    对于程序的复合而言,好的代码是它的表面积要比体积增长的慢。

    代码块的“表面积”是我们复合代码块时所需要的信息(接口API协议定义)。代码块的“体积”就是接口内部的实现逻辑(API内部的实现代码)。

    在OOP中,一个理想的对象应该是只暴露它的抽象接口(纯表面, 无体积),其方法则扮演箭头的角色。如果为了理解一个对象如何与其他对象进行复合,当你发现不得不深入挖掘对象的实现之时,此时你所用的编程范式的原本优势就荡然无存了。

    FP通过函数组合来构造其逻辑系统。FP倾向于把软件分解为其需要执行的行为或操作,而且通常采用自底向上的方法。函数式编程也提供了非常强大的对事物进行抽象和组合的能力。

    在FP里面,函数是“一类公民”(first-class)。它们可以像1, 2, “hello”,true,对象…… 之类的“值”一样,在任意位置诞生,通过变量,参数和数据结构传递到其它地方,可以在任何位置被调用。

    而在OOP中,很多所谓面向对象设计模式(design pattern),都是因为面向对象语言没有first-class function(对应的是多态性),所以导致了每个函数必须被包在一个对象里面(受约束的函数指针)才能传递到其它地方。

    函数式编程基本特性

    在经常被引用的论文 “Why Functional Programming Matters” 中,作者 John Hughes 说明了模块化是成功编程的关键,而函数编程可以极大地改进模块化。

    在函数编程中,我们有一个内置的框架来开发更小的、更简单的和更一般化的模块, 然后将它们组合在一起。

    函数编程的一些基本特点包括:

    • 函数是”第一等公民”。
    • 闭包(Closure)和高阶函数(Higher Order Function)。
    • Lambda演算与函数柯里化(Currying)。
    • 懒惰计算(lazy evaluation)。
    • 使用递归作为控制流程的机制。
    • 引用透明性。
    • 没有副作用。

    参考出处:https://blog.csdn.net/axi295309066/article/details/78040241

  • 相关阅读:
    【NOIP2018】游记
    题解 P1441 【砝码称重】
    题解 P3128 【[USACO15DEC]最大流Max Flow】
    题解 P1949 【聪明的打字员_NOI导刊2011提高(10)】
    题解 P1966 【火柴排队】
    题解 P1895 【数字序列】
    topcoder做题
    1149E
    hdu 6589
    hdu 6579
  • 原文地址:https://www.cnblogs.com/wwwlinguangcom/p/9908674.html
Copyright © 2011-2022 走看看