函数式语言 函数式编程 利用若干简单的执行单元让计算结果不断渐进,逐层推导复杂的运算

 小结:

1、

不修改状态。在函数式编程中,程序语言在使用中是会不修改变量的,它的一个特性可以使得函数式编程语言区别于其他的程序语言。在其他类型的语言中,变量是用来保存状态的。由于函数式编程不修改变量,导致了这些状态不能存在于变量中。那么,函数式编程语言保存状态的方法是使用参数来保存,递归方法是最好的例子。由于采用了递归方法,函数式编程语言在运行速度上相对于其他语言较慢,所以,速度不够快是函数式编程语言长期不能广泛使用的主要原因。

在函数式程序语言中,所有的功能的结果就是一个返回值,不存在其他的行为,包括对外部变量的修改。

程序员在进行函数式编程时完全不用考虑死锁的问题,因为它根本就不修改变量,所以就不存在锁线程的问题;

 2、

强调程序执行的结果而非执行的过程,倡导利用若干简单的执行单元让计算结果不断渐进,逐层推导复杂的运算,而不是设计一个复杂的执行过程

https://baike.baidu.com/item/函数式编程/4035031?fr=aladdin

https://baike.baidu.com/item/函数式语言/7663961?fr=aladdin

函数式语言(functional language)一类程序设计语言,是一种非冯·诺伊曼式的程序设计语言。函数式语言主要成分是原始函数、定义函数和函数型。这种语言具有较强的组织数据结构的能力,可以把某一数据结构(如数组)作为单一值处理;可以把函数作为参数,其结果也可为函数,这种定义的函数称为高阶函数,程序就是函数,程序作用在结构型数据上,产生结构型结果,从根本上改变了冯·诺伊曼式语言的“逐词”工作方式。
 
中文名
函数式语言
外文名
functional language
学    科
计算机科学
定    义
非冯·诺伊曼式的程序设计语言
特    点
并行、单元测试等
优    点
代码管理更加方便

介绍

编辑
由于计算机技术的不断发展,函数式编程语言逐渐得到人们的重视。我们现在使用的大多数编程语言大都是以冯诺伊曼式的计算机为设计背景,所以我们称这些计算机编程语言为诺伊曼式语言。1977年,John Backus提出了函数式编程语言,这种语言以非冯诺伊曼式的计算机为设计而背景,所以我们又称这样的函数式编程语言称为非冯诺伊曼式语言。函数式编程,又称泛函编程,是一种编程范型,它将电脑运算视为数学上的函数计算,并且避免状态以及可变数据。函数编程语言最重要的基础是λ演算。而且λ演算的函数可以接受函数当作输入(引数)和输出(传出值)。和命令式编程相比,函数式编程强调函数的计算比指令的运行重要。和程序编程相比,函数式编程裹,函数的计算可随时调用。
Haskell是一种于1980年代末期所发布的函数式编程语言,Haskell函数式编程语言是在Miranda的基础上得到了,它对Miranda进行了标准化,所以这种语言集合了其他相关函数式编程开发的原理,它无需花费太多的赘述就能完成一些数据结构,比如链表和矩阵,是当前最广泛地被用于研究的一种函数式编程语言。它的语言衍生物有很多,有扩充Haskell、并行Haskell和面向对象的变体如Mondrian等。与此同时,它还被用作为在新语言设计时的标准模板。
另一种函数式编程语言是Clean,它和Haskell有很多一样的地方。目前这门语言是用C写成的,由尼兹梅根大学负责维护。
还有一种函数式编程语言是Meta Language, MetaLanguage是由爱丁堡大学与上个世纪七十年代末所开发的,它被归类为非纯函数式编程语言,它之所以有这样的归类是因为它允许了副作用和指令式编程的使用。 目前,函数式编程语言还有F#,这是一款针对.NET平台的开放研究的语言。 [1] 

语言的特点

编辑
函数式编程经常使用递归。纯函数式的程序没有变量和副作用(Side effect)。因为纯函数式程序设计语言没有变量,函数没有副作用,编写出的程序可以利用记忆化、公共子表达式消除和并发计算在运行时和编译时得到大量优化。我们常见的编程语言有数十种之多。编程语言种类有很多,如果按照程序设计的方法,可分为以下几种程序语言:
(1)结构化编程语言,比如C语言等。
(2)函数式编程语言,比如OCaml, Lisp等。
(3)逻辑式编程语言,比如Prolog等。
(4)面向对象程序语言,比如Java等。
通过比较可以发现,函数式编程语言有以下几个特点:
1、并行。在函数式编程中,程序员无需对程序修改,程序就可以并发运行。程序运行期间,不会产生死锁现象。原因是通过函数式编程所得到的程序,在程序中不会出现某一数据被同时修改两次及以上的情况,同样的,两个不同的线程就更不用说了。由于函数式编程有这样的优点,导致了程序员完全不用花费精力去考虑增加某个线程带来的并发问题。
在函数编程语言中,编译器会分析代码,辨认出潜在耗时的创建字符串s1和s2的函数,然后将他们并行的运行。这样的做法,是程序员在使用普通的命令式程序语言时不可能做到的。而使用函数式程序语言可以自动的找出那些可以并发执行的函数。
2、单元测试。在函数式编程中,由于程序中的每一个符号都是final后的,所以这样的函数不会产生副作用。这就导致了在某个地方产生修改,同时不会有函数修改过在自身范围之外的变量或者状态被另外的函数所使用。这就导致了函数的返回结果只是返回值。只有函数自身的参数才会影响函数的返回值,所以在编程的时候,对程序中的每个函数而言,程序员只需在控制它们的参数,而不用在意函数自己点顺序以及函数外部变量和状态就能正确的编程。与函数式编程相比,命令式编程就没有这样的优势了,在检查函数的返回值的同时程序员还必须检查函数是否影响到了函数的外部状态和变量。
3、没有额外作用。副作用是指的是函数内部与外部互动。比如,函数在自身内部可以对函数以外的其他变量进行修改,这样就会产生其他结果。在函数式编程中,想要达到这样的目的就必须让函数自身要保持独立。在函数式程序语言中,所有的功能的结果就是一个返回值,不存在其他的行为,包括对外部变量的修改。
4、不修改状态。在函数式编程中,程序语言在使用中是会不修改变量的,它的一个特性可以使得函数式编程语言区别于其他的程序语言。在其他类型的语言中,变量是用来保存状态的。由于函数式编程不修改变量,导致了这些状态不能存在于变量中。那么,函数式编程语言保存状态的方法是使用参数来保存,递归方法是最好的例子。由于采用了递归方法,函数式编程语言在运行速度上相对于其他语言较慢,所以,速度不够快是函数式编程语言长期不能广泛使用的主要原因。
5、引用透明。在函数式编程中,引用透明指的是运行函数的时候,函数的没一个步骤都不会不牵连到函数的外部变量或状态,而是只依赖于函数输入的参数,相同的参数输入总会得到相同的函数返回值。而在其他类型的语言中,函数的返回值不仅仅与函数的参数传入有关,也与当前的系统状态有关。在不同的系统状态的情况下,函数的返回值不同。
6、代码部署热。在以前,假如想在Windows上安装更新,安装之后重启计算机是必须进行的步骤,可能还不只一次的重启。即使是仅仅安装了一个小的软件也不能免于重启的步骤。一些特殊的系统,比如电信系统,这样的系统必须保证任何时间都在运行。因为如果在系统更新时紧急拨号失效,就可能造成很大的损失。最理想的情况是在完全不停止系统任何组件的情况下,达到更新相关的代码的目的。这样的想法在命令式编程中是不可能的。对函数式的程序,所有的状态即传递给函数的参数都被保存在了堆栈上,这使的热部署轻而易举。实际上,所有我们需要做的就是对工作中的代码和新版本的代码做一个差异比较,然后部署新代码。其他的工作将由一个语言工具自动完成。

使用意义

编辑
函数式编程语言相对于其他编程语言具有以下意义:首先,函数式编程语言的代码十分简单,加快了开发的速度。并且由于在使用函数式编程语言时,程序员会大量使用到函数,从而减少了重复的代码,因而程序比较短。其次,函数式编程语言更加接近我们使用的自然语言,程序员在学习和使用它的时候更加快捷容易。函数式编程语言的自由度很高,十分接近自然语言写出的代码。另外,函数式编程语言的代码管理更加方便。函数式编程不会对外部产生依赖,也不会修改外界的状态。程序员只需把指定的参数给函数,相同的参数其返回的结果必定是相同的。另外,函数式编程语言还支持并发编程,这就使得程序员在进行函数式编程时完全不用考虑死锁的问题,因为它根本就不修改变量,所以就不存在锁线程的问题。最后,函数式编程语言的代码支持代码热升级。 [2] 
 
 
 
 
函数式编程是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambda calculus),而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。 [1] 
和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。
和过程化编程相比,函数式编程里函数的计算可随时调用。
 
中文名
函数式编程
外文名
Functional Programming
类    型
编程范式
原    理
将电脑运算视为函数的计算
基    础
λ演算
主要思想
把运算过程写成嵌套函数调用

目录

  1. 历史
  2. 定义
  1. 例子
  2. 特性
  1. 优点
  2. 顾虑

历史

编辑
虽然 λ 演算并非设计来于计算机上执行,但可视为第一个函数式编程语言。1980年代末期,Haskell发布企图集合很多函数式编程研究里的想法。 [2] 

定义

编辑
简单说,"函数式编程"是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论。
它属于"结构化编程"的一种,主要思想是把运算过程尽量写成一系列嵌套的函数调用。 [2] 

例子

编辑
函数式编程中最古老的例子莫过于1958年被创造出来的LISP了,透过 LISP,可以用精简的人力。较现代的例子包括Haskell、Clean、Erlang和Miranda等。 [3] 

特性

编辑
闭包和高阶函数
函数编程支持函数作为第一类对象,有时称为闭包或者仿函数(functor)对象。实质上,闭包是起函数的作用并可以像对象一样操作的对象。与此类似,FP 语言支持高阶函数。高阶函数可以用另一个函数(间接地,用一个表达式) 作为其输入参数,在某些情况下,它甚至返回一个函数作为其输出参数。这两种结构结合在一起使得可以用优雅的方式进行模块化编程,这是使用 FP 的最大好处。 [4] 
惰性计算
除了高阶函数和仿函数(或闭包)的概念,FP 还引入了惰性计算的概念。在惰性计算中,表达式不是在绑定到变量时立即计算,而是在求值程序需要产生表达式的值时进行计算。延迟的计算使您可以编写可能潜在地生成无穷输出的函数。因为不会计算多于程序的其余部分所需要的值,所以不需要担心由无穷计算所导致的 out-of-memory 错误。一个惰性计算的例子是生成无穷 Fibonacci 列表的函数,但是对第n个Fibonacci 数的计算相当于只是从可能的无穷列表中提取一项。
递归
FP 还有一个特点是用递归做为控制流程的机制。例如,Lisp 处理的列表定义为在头元素后面有子列表,这种表示法使得它自己自然地对更小的子列表不断递归。
函数式编程具有五个鲜明的特点。
函数是"第一等公民"
所谓"第一等公民"(first class),指的是函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。
举例来说,下面代码中的print变量就是一个函数,可以作为另一个函数的参数。
var print = function(i){ console.log(i);};
  [1,2,3].forEach(print);
只用"表达式",不用"语句"
"表达式"(expression)是一个单纯的运算过程,总是有返回值;"语句"(statement)是执行某种操作,没有返回值。函数式编程要求,只使用表达式,不使用语句。也就是说,每一步都是单纯的运算,而且都有返回值。
原因是函数式编程的开发动机,一开始就是为了处理运算(computation),不考虑系统的读写(I/O)。"语句"属于对系统的读写操作,所以就被排斥在外。
当然,实际应用中,不做I/O是不可能的。因此,编程过程中,函数式编程只要求把I/O限制到最小,不要有不必要的读写行为,保持计算过程的单纯性。
没有"副作用"
所谓"副作用"(side effect),指的是函数内部与外部互动(最典型的情况,就是修改全局变量的值),产生运算以外的其他结果。
函数式编程强调没有"副作用",意味着函数要保持独立,所有功能就是返回一个新的值,没有其他行为,尤其是不得修改外部变量的值。
不修改状态
上一点已经提到,函数式编程只是返回新的值,不修改系统变量。因此,不修改变量,也是它的一个重要特点。
在其他类型的语言中,变量往往用来保存"状态"(state)。不修改变量,意味着状态不能保存在变量中。函数式编程使用参数保存状态,最好的例子就是递归。下面的代码是一个将字符串逆序排列的函数,它演示了不同的参数如何决定了运算所处的"状态"。
引用透明性
函数程序通常还加强引用透明性,即如果提供同样的输入,那么函数总是返回同样的结果。就是说,表达式的值不依赖于可以改变值的全局状态。这使您可以从形式上推断程序行为,因为表达式的意义只取决于其子表达式而不是计算顺序或者其他表达式的副作用。这有助于验证正确性、简化算法,甚至有助于找出优化它的方法。
副作用
副作用是修改系统状态的语言结构。因为 FP 语言不包含任何赋值语句,变量值一旦被指派就永远不会改变。而且,调用函数只会计算出结果 ── 不会出现其他效果。因此,FP 语言没有副作用。 [5] 

优点

编辑
1. 代码简洁,开发快速
函数式编程大量使用函数,减少了代码的重复,因此程序比较短,开发速度较快。
Paul Graham在《黑客与画家》一书中写道:同样功能的程序,极端情况下,Lisp代码的长度可能是C代码的二十分之一。
如果程序员每天所写的代码行数基本相同,这就意味着,"C语言需要一年时间完成开发某个功能,Lisp语言只需要不到三星期。反过来说,如果某个新功能,Lisp语言完成开发需要三个月,C语言需要写五年。"当然,这样的对比故意夸大了差异,但是"在一个高度竞争的市场中,即使开发速度只相差两三倍,也足以使得你永远处在落后的位置。"
2. 接近自然语言,易于理解
函数式编程的自由度很高,可以写出很接近自然语言的代码。
前文曾经将表达式(1 + 2) * 3 - 4,写成函数式语言:
subtract(multiply(add(1,2), 3), 4)
对它进行变形,不难得到另一种写法:
add(1,2).multiply(3).subtract(4)
这基本就是自然语言的表达了。再看下面的代码,大家应该一眼就能明白它的意思吧:
merge([1,2],[3,4]).sort().search("2")
因此,函数式编程的代码更容易理解。
3. 更方便的代码管理
函数式编程不依赖、也不会改变外界的状态,只要给定输入参数,返回的结果必定相同。因此,每一个函数都可以被看做独立单元,很有利于进行单元测试(unit testing)和除错(debugging),以及模块化组合。
4. 易于"并发编程"
函数式编程不需要考虑"死锁"(deadlock),因为它不修改变量,所以根本不存在"锁"线程的问题。不必担心一个线程的数据,被另一个线程修改,所以可以很放心地把工作分摊到多个线程,部署"并发编程"(concurrency)。
请看下面的代码:
var s1 = Op1();
var s2 = Op2();
var s3 = concat(s1, s2);
由于s1和s2互不干扰,不会修改变量,谁先执行是无所谓的,所以可以放心地增加线程,把它们分配在两个线程上完成。其他类型的语言就做不到这一点,因为s1可能会修改系统状态,而s2可能会用到这些状态,所以必须保证s2在s1之后运行,自然也就不能部署到其他线程上了。
多核CPU是将来的潮流,所以函数式编程的这个特性非常重要。
5. 代码的热升级
函数式编程没有副作用,只要保证接口不变,内部实现是外部无关的。所以,可以在运行状态下直接升级代码,不需要重启,也不需要停机。Erlang语言早就证明了这一点,它是瑞典爱立信公司为了管理电话系统而开发的,电话系统的升级当然是不能停机的。

顾虑

编辑
函数式编程常被认为严重耗费在CPU和存储器资源。主因有二:
  • 早期的函数式编程语言实现时并无考虑过效率问题。
  • 有些非函数式编程语言为求提升速度,不提供自动边界检查或自动垃圾回收等功能。
惰性求值亦为语言如Haskell增加了额外的管理工作。
 
 
 
 
https://zh.wikipedia.org/wiki/函数式编程

函数式编程英语:functional programming)或称函数程序设计泛函编程,是一种编程范式,它将计算机运算视为函数运算,并且避免使用程序状态以及易变对象。其中,λ演算(lambda calculus)为该语言最重要的基础。而且,λ演算的函数可以接受函数当作输入(引数)和输出(传出值)。

比起指令式编程,函数式编程更加强调程序执行的结果而非执行的过程,倡导利用若干简单的执行单元让计算结果不断渐进,逐层推导复杂的运算,而不是设计一个复杂的执行过程。

 
原文地址:https://www.cnblogs.com/rsapaper/p/10515916.html