热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

函数式编程介绍

本文将描述函数式编程的基本理论,从而让你理解什么是函数式编程,同时也会展示“函数式编程”和“面向对象”这两种不同风格的编程范式之间的区别。本文是函数式编程系列的入门篇,后续文章陆续

本文将描述函数式编程的基本理论,从而让你理解什么是函数式编程,同时也会展示“函数式编程”和“面向对象”这两种不同风格的编程范式之间的区别。本文是函数式编程系列的入门篇,后续文章陆续会发出。

什么是函数

函数式编程背后的理论依据是数学,数学函数背后有一系列有意思的特点,而函数式编程语言则试图模拟这些特性。
让我们先来看一个简单的数学函数:

y =  x + 1

这个数学函数的意图是显而易见的,给定一个变量x然后返回x + 1, 上面的数学函数用C#来表示:

public int Add1(int x)
{
    return x + 1;
}

数学函数跟我们用命令式语言编写的函数相比有两个明显的区别:

  • 同一个输入在数学函数里总能得到相同的返回值
  • 数学函数没有副作用
  • 输入值和输出值是不变的(immutable)

这三个区别具体是什么意思呢?

同一个输入在数学函数里总能得到相同的返回值

在命令式语言(imperative programming)中,我们总是在函数内部做一些计算和处理,然后返回最终结果。在数学函数中没有计算和处理,你可以认为数学函数的返回值是对输入值的一一映射。上面提到的数学函数极端定义如下:

int Add1(int x)
{ 
   switch (x)
   {
   case 0: return 1;
   case 1: return 2;
   case 2: return 3;
   case 3: return 4;
   //...
   }
}

当然现实环境中我们不会写出这样的代码,但是数学函数的思想是类似的,里面没有对事情的处理逻辑。
关于命令式语言和声明式语言的区别看这里:命令式语言和声明式语言的区别

数学函数没有副作用

数学函数所做的事就是根据每一个输入返回不同的输出,整个过程没有对输入值做任何改变,在返回输出的过程中也没有对其他的任何环境造成影响,在函数式语言里这样的函数被称为纯函数

输入值和输出值是不变的

immutable使得代码更加具有预测性,考虑下面的代码:

public int Add1(int x)
{
    x = 2;
    return x + 1;
}

public void InvokeAdd1()
{
    var x = 10;
    var y = Add1(x);

    Console.WriteLine($"x={x}, y={y}");
}

你试图在Add1函数中实现y = x + 1,但是由于失误将x的值改为了2,从而导致了一个bug,immutable则强制你无法修改x的值,一旦初始化就不能再修改。显然C#默认是mutable的,但在常见的函数式语言中,变量声明式immutable的,比如在F#中将x初始化为6然后再修改为7会编译出错:

let x = 6
x <- 7

作为一个修炼命令式语言多年的开发者也许会内心充满疑问,无法修改变量真的靠谱?答案是肯定的,在后面的文章中将会展示这种用法。

纯函数带来的好处

看似不起眼的三个特点实际上会带来非常强大的益处,所以函数式编程语言则试图把这三个特性带到他们的设计当中。

得益于纯函数的这种特点,对同一个输入无论你重复调用多次,都会返回同样的结果,并且没有副作用,因此:

  • 所有的调用可以使并行的。 加入你想用1到10000之间的数字去调用Add1函数,你可以把这些计算过程分配到10个不同的CPU上并行执行,由于所有的调用都是没有副作用的,所以你不需要使用命令式语言中的锁机制就能完成任务;
  • 懒加载成为现实,你可以在真正需要结果的时候去执行计算,因为你可以保证在任何时刻对同一个输入返回的结果总是相同的
  • 你可以对函数的计算结果进行缓存,因为相同的输入总能得到相同的结果,所以可以轻而易举的对函数增减缓存功能

后续文章即将发出,请想了解函数式编程的童鞋支持并关注。


推荐阅读
  • switch语句的一些用法及注意事项
    本文介绍了使用switch语句时的一些用法和注意事项,包括如何实现"fall through"、default语句的作用、在case语句中定义变量时可能出现的问题以及解决方法。同时也提到了C#严格控制switch分支不允许贯穿的规定。通过本文的介绍,读者可以更好地理解和使用switch语句。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • 服务器上的操作系统有哪些,如何选择适合的操作系统?
    本文介绍了服务器上常见的操作系统,包括系统盘镜像、数据盘镜像和整机镜像的数量。同时,还介绍了共享镜像的限制和使用方法。此外,还提供了关于华为云服务的帮助中心,其中包括产品简介、价格说明、购买指南、用户指南、API参考、最佳实践、常见问题和视频帮助等技术文档。对于裸金属服务器的远程登录,本文介绍了使用密钥对登录的方法,并提供了部分操作系统配置示例。最后,还提到了SUSE云耀云服务器的特点和快速搭建方法。 ... [详细]
  • 本文讨论了编写可保护的代码的重要性,包括提高代码的可读性、可调试性和直观性。同时介绍了优化代码的方法,如代码格式化、解释函数和提炼函数等。还提到了一些常见的坏代码味道,如不规范的命名、重复代码、过长的函数和参数列表等。最后,介绍了如何处理数据泥团和进行函数重构,以提高代码质量和可维护性。 ... [详细]
  • Java SE从入门到放弃(三)的逻辑运算符详解
    本文详细介绍了Java SE中的逻辑运算符,包括逻辑运算符的操作和运算结果,以及与运算符的不同之处。通过代码演示,展示了逻辑运算符的使用方法和注意事项。文章以Java SE从入门到放弃(三)为背景,对逻辑运算符进行了深入的解析。 ... [详细]
  • 本文介绍了PHP常量的定义和使用方法,包括常量的命名规则、大小写敏感性、全局范围和标量数据的限制。同时还提到了应尽量避免定义resource常量,并给出了使用define()函数定义常量的示例。 ... [详细]
  • Java和JavaScript是什么关系?java跟javaScript都是编程语言,只是java跟javaScript没有什么太大关系,一个是脚本语言(前端语言),一个是面向对象 ... [详细]
  • 2016 linux发行版排行_灵越7590 安装 linux (manjarognome)
    RT之前做了一次灵越7590黑苹果炒作业的文章,希望能够分享给更多不想折腾的人。kawauso:教你如何给灵越7590黑苹果抄作业​zhuanlan.z ... [详细]
author-avatar
je荒也是种美
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有