`

函数式编程(一) 认识“编程范式”和“函数”

阅读更多

 

编程范式(Programming paradigm)

 

  编程范式指我们在编写程序解决问题的思路和视角。它提供了同时也决定了程序员对程序运行的看法。计算机编程中存在许多编程范式,如命令式编程、声明式编程、面向对象编程以及结构化编程等等。其中面向对象编程范式认为程序是由一系列相互作用的对象组成,而结构化编程范式认为程序采用子程序、代码区块、for循环以及while循环等结构组成。下面主要说明本篇文章将要讲到的命令式编程范式和声明式编程范式。

 

1)命令式编程(Imperative):

 

     强调程序代码模拟电脑运行过程,强调“先做什么”、“再做什么”。如果我们要计算“2*3+1”,我们编写代码时先计算2*3存入临时变量,再计算该临时变量与1的和。命令式编程是当前主流编程范式,我们编写的代码几乎都属于命令式编程范式。

 

2)声明式编程(Declarative):

 

     强调程序代码模拟人脑计算过程,强调“最终要什么”,相比命令式编程范式来讲,它更看重结果而非过程。声明式编程范式更接近人类思想,它的思考层面要高于命令式编程。

 

下图显示了命令式编程范式与声明式编程范式的区别:

 


图1

 

         注:各种编程范式之间并非都是对立的,很多范式是从不同角度来划分的。如面向对象编程范式同时也属于命令式编程范式。当然,本篇文章讲到的“命令式编程范式”和“声明式编程范式”两者是对立的。

 

 

 

声明式编程范式 

 

  声明式编程范式常见有以下两种(最常见):

 

1)领域特定语言(Domain Specific Language,DSL):

 

  名字很陌生,但是我们却经常在用。如SQL、CSS以及正则表达式等等。这些语言只在特定领域起作用,并且使用这些语言时,我们大多数时候是在写“陈述、声明”的语句。如“select * from tb”,我们只关心我们要的结果,而不用去关系具体实现。

 

2)函数式编程(Functional Program,FP):

 

  函数式编程是我们要讨论的重点。既然它属于声明式编程范式,那么它也应该强调结果(What)而非过程(How)。没错,函数式编程不同于常见的命令式编程,它不关心计算机具体的实现过程,而仅仅注重问题结果。

 

 

 

函数式编程(Functional Program):

 

  网上关于“函数式编程”的解释有很多,但大多数都比较模糊抽象。维基百科上对函数式编程的解释是“In computer science, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data”,翻译成中文就是“函数式编程是一种编程范式,它将计算机运算看作是数学中函数的计算,并且避免了状态以及变量的概念”。这是个什么意思呢?很多文章分别从函数式编程的几个特点上做出了解释,比如“函数是第一公民”、“高阶函数(Higher Order Function)”、“无状态性(No State)”、“无副作用性(Side-Effect)”、“易于并行开发”以及“惰性求值”等等。但是我觉得这些都只是函数式编程的特点或者说是优点,并没有实质上解释出“函数式编程”与普通命令式编程的区别。我认为要搞清楚函数式编程,必须先认清“函数”的概念。没错,虽然我们自认为我们比较熟悉“函数”(或者叫“方法”,本文不区分这两者的区别),但是我们真的熟悉它们吗?

 

 

编程函数和数学函数:

 

     第一次了解“函数”的概念应该是我们读中学时,“y=x+1”在平面坐标系中是一条直线,到后来(不知道哪年级)学习了二次函数,“y=x^2+2*x+1”在平面坐标系中是一条抛物线。当时学习函数时知道以下知识点:

 

1)函数是一种映射,自变量经由一种映射关系变换后,得到因变量(函数值);

 

2)对于每个自变量,均能、有且仅有一个因变量与之对应,这是函数的确定性。也就是说,给定一个自变量,任何时候函数值都唯一;

 

那么,到大学学习编程后(本人读大学才开始学习编程),我们在程序中又遇见了“函数”,很熟悉的感觉。但是它和数学中的函数有什么关联呢?也就是说,数学思想与我们编程思想是否有关联?如果以我们目前写C#、Java、C++等代码来看,它们几乎没有关系,因为我们程序中的函数可以没有参数(数学函数中的“自变量”),也可以没有返回值(数学函数中的因变量),就算一个函数有返回值,那么给定参数,调用函数后每次运行结果也可能不一样。以上这些均不能满足数学函数的概念。其实出现“两种函数几乎无关系”的现象很容易理解,数学描述的是人类思维过程,而我们(目前大部分人)编写的程序代码描述的是计算机运行过程。在数学家与程序员之间早已产生了沟通障碍,比如下图:

 

 


图2

 

如上图所示,“X=X+1”这种表达式如果从数学角度来看,几乎是不可成立的,让任何一个没有学过编程的人去看这个表达式,TA都会以为你写的是错的,他们只认“Y=X+1”。原因很简单,在程序中,符号可以代表变量,而变量表示一个内存单元,该内存处的值可以被重写(赋值);而在数学中,符号永远只是符号,等号“=”两边表示等价关系,“Y=X+1”表示Y与X+1是等价的,Y仅仅是X+1的一个代替符号。

 

  同理,函数也一样。数学中的函数仅仅描述一种“映射关系”,给定一个自变量,我们可以得到一个因变量,仅此而已。而程序中的函数更多的时候扮演的是一种“功能”角色,它能够完成指定任务。当然,如果程序中一个函数包含参数,并且能够返回值,那么它完全可以模拟数学函数。下面使用C#编写一个委托,它代表数学中的一个一元函数:

public delegate double Function1X(double x);

 

如上代码所示,委托签名中包含一个double类型参数,并且返回一个double类型返回值。数学中的“f(x)=x^2+2*x+1”可以使用C#编写以下函数:

public double f(double x) {
     return Math.Pow(x,2) + 2*x + 1;
}

函数f(x)在x=2处的值调用代码:f(2);。或者使用Lambda表达式:

 

x => Math.Pow(x,2) + 2*x + 1;

 

程序中的函数接收一个double类型参数,经过映射关系,返回一个double类型的返回值,它与“f(x)=x^2 + 2*x +1”对应。那么数学函数中的二元函数在程序中怎样表示呢?很简单,二元函数包含两个自变量,我们只需要为程序中函数定义两个参数即可:

public delegate double Function2XY(double x,double y);

 

如上代码所示,委托签名中包含两个double类型参数,并且返回一个double类型返回值。

 

  从上面的介绍可以看出,如果将程序中函数做一些限制,那么它就可以模拟数学中的函数了:

 

1)每个函数必须包含输入参数(作为自变量);

 

2)每个函数必须有返回值(作为因变量);

 

3)无论何时,给定参数调用函数时,返回值必须一致。

 

上面第三条限制是为了满足函数的“确定性”,该条限制要求程序中的函数执行期间不能依赖于外界因素,也不要影响外部环境。换句话说,它在执行期间与外界是隔绝的。我们将满足以上条件的函数称为“纯函数(Pure Function)”。纯函数与外界交互只有一条渠道——传入参数与返回值。纯函数也不读取/改变全局变量、无IO操作等。



 图3

 

纯函数是程序代码模拟数学函数的基础。理论上讲,函数式编程中,函数是第一公民的同时,所有函数也都应该属于“纯函数”。到此,我们再回过头看一下维基百科上对“函数式编程”的解释:函数式编程是一种编程范式,它将计算机运算看作是数学中函数的计算,并且避免了状态以及变量的概念。很显然,函数式编程向数学验算靠拢,使用一种平时正常的数学思维去解决问题。

 

         注:函数式编程是基于“lambda验算(Lambda Calculus)”的,它并不属于“图灵机”理论范畴。我没搞清楚lambda验算,所以本文并没详细提到。看到Lambda很容易让我们想到C#3.0中引入的Lambda表达式,这不是偶然。C# 3.0之后开始支持“函数式编程”,后面文章将会讲到。

 

文章摘自:http://blog.csdn.net/vonsdite/article/details/76796557

  • 大小: 10.1 KB
  • 大小: 5.7 KB
  • 大小: 15.2 KB
分享到:
评论

相关推荐

    函数式编程从崛起到没落到再崛起共2页.pdf.zip

    函数式编程是一种编程范式,它强调通过使用数学函数来构造计算,而不是通过改变状态或控制流程。在函数式编程中,程序被视为一系列不可变的数据转换,而不是指令集。这种编程风格最早可以追溯到20世纪30年代的λ演算...

    华中科技大学-函数式编程原理实验内含源码和说明书.zip

    《函数式编程原理》实验资源包含了多个实验项目和相关材料,...综上所述,这份实验资源为学习者提供了丰富的实践机会,通过亲自动手编码和理解函数式编程的基本原理,可以深化对这一编程范式的认识,并提升编程技能。

    快学Scala课后习题答案

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的概念。"快学Scala"可能是一个针对初学者的教程或课程,旨在帮助学习者迅速掌握这门语言的基础和高级特性。课后习题是检验学习效果、加深理解的重要...

    《JavaScript函数式编程》读后感

    在深入学习函数式编程的过程中,我认识到,它与传统的面向过程和面向对象编程有着显著的区别。函数式编程的核心理念是将程序视为一系列数学函数的组合,强调通过纯函数(即无副作用、仅依赖于输入参数的函数)来构建...

    功能C(Pieter Hartel,Henk Muller)Functional C (Pieter Hartel, Henk Muller )

    综上所述,《功能C》是一本针对已有函数式编程基础的学生,进一步介绍和教授命令式编程范式的教材。通过这本书,学生可以学习到如何使用C语言这种低级的命令式编程语言来编写程序,并且能够在这一过程中理解命令式...

    Scala编程(中文完整版)

    Scala是一种多范式的编程语言,它融合了面向对象和函数式编程的特点,设计目标是提供一种静态类型系统,同时保持代码简洁和可读性。Scala运行在Java虚拟机(JVM)上,能够无缝地与Java库进行交互,这使得它在开发大...

    A Functional Pattern System for oo design

    2. 函数式编程作为一种与面向对象互补的编程范式,其核心概念可以为面向对象设计带来新的视角和解决方案。 3. 设计模式在软件工程中起到模板的作用,能够帮助开发者以结构化的方式解决设计问题。 4. 面向对象设计...

    新一代编程语言Python、MATLAB和Haskell.pdf

    函数式编程的一个关键思想是函数是一等公民,即函数可以像任何其他数据类型一样被传递和操作。Haskell的这些特性使得它特别适合于进行复杂算法的实现和研究。然而,函数式编程对于习惯了传统编程范式的开发者来说...

    带你认识常用的编程语言.pdf

    - 多范式:支持面向对象、面向过程和函数式编程。 - 应用广泛:Python常用于Web开发、数据分析、人工智能(AI)等领域,尤其是神经网络和自然语言处理(NLP)。 然而,Python的执行速度相对较慢,因为它依赖于解释...

    haskell趣学指南 高清

    此外,由于Haskell与众不同的编程范式,该指南可能会特别强调函数式编程的相关概念,如高阶函数、纯函数、惰性求值、模式匹配和类型系统等。这些知识点是Haskell程序设计的核心,并且对于理解现代编程语言的发展趋势...

    抽象论域到数据结构的转换.pdf

    通过这些知识点,我们可以更深入地了解函数式编程与过程式编程之间的差异,以及如何将理论转换为实际应用中有效的数据结构和算法。同时,对于编程语言的设计、语义和编译原理也有了一定的认识。

    07丨编程语言原理:面向对象编程是编程的终极形态吗?.pdf

    函数式编程(Functional Programming,FP)强调纯函数、无副作用和状态不变性,它在并行计算和处理大量数据的场景下表现优异。另外,过程式编程(Procedural Programming)和声明式编程(Declarative Programming)...

    快学Scala 中文版带目录

    Scala是一种多范式编程语言,融合了面向对象和函数式编程的特点,广泛应用于大数据处理、云计算以及高性能计算等领域。 目录作为书中的导航系统,对于学习者来说至关重要,它清晰地展示了Scala学习路径的全貌。通过...

    带你认识常用的编程语言.docx

    它支持多种编程范式,包括面向对象、面向过程和函数式编程。Python拥有丰富的标准库,特别适合神经网络和自然语言处理。Python可在多个操作系统上运行,但其解释器导致的执行速度较慢,不适合对性能要求极高的移动...

    面向对象设计的功能模式系统A Functional Pattern System for Object-Oriented Design

    这一理论的提出基于对面向对象编程范式(OOP)的局限性的认识,即OOP虽然显著提高了设计和维护大型复杂软件系统的能力,但在代码重用性和系统演进的简易性方面,并未达到预期效果。作者认为这种不足源于多种可能的...

    Scala By Examples

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的特点。"Scala By Example" 是一本专为学习Scala编程所编写的实践指南,旨在通过实例帮助初学者更好地理解和掌握这门语言。 在书的第一部分,"A ...

    Springer.The Mathematica Guidebook Programming

    在基础语法章节中,讲解了通用快捷键、括号、注释、字体使用以及引用输出等内容,强调了函数式编程风格和代码的“理想”格式化。 书中还包含了许多入门示例,涵盖了数学、科学和工程学等领域的具体应用场景,如周期...

Global site tag (gtag.js) - Google Analytics