zoukankan      html  css  js  c++  java
  • 函数式编程(一):纯函数

    其他:
    函数式编程(二):curry

    函数式编程(三):组合函数

    前言:这个系列是在读《JS函数式吧编程指南》时,做的笔记。

    函数式编程与面向对象编程

    首先这两种思想不一定就是互斥的,就像 JavaScript,Ruby,Python 也是同时柔和了两种思想的好处。的确,两样东西看起来像是不同层面的东西,函数式编程对应的应该是指令式编程,而面向对象编程更多是一种抽象现实模型的一种设计思路。

    面向对象强调数据与行为的绑定,行为(方法)围绕着数据来展开。而函数式编程则倾向于函数与数据的等价,所谓的函数“一等公民”,也就是函数也被看作一种数据,可以作为参数,可以作为返回值。

    函数式编程在理论上基于 Lambda 演算,而指令式编程基于图灵机。现在的机器的指令集都是基于图灵机的,也就是硬件实现上都是基于图灵机,函数式编程最后还得编译为图灵机的二进制。函数式的执行效率不高。

    函数式编程的特点:表达式化,高阶逻辑(告诉计算机做什么,而不是怎么做)组合子逻辑(自底向上设计)

    什么是纯函数?

    纯函数是这样一种函数,即相同的输出,永远会得到相同的输出,而且没有任何可观察的副作用。相同的输入,永远会得到相同的输出,意味着对外部状态的解耦。

    ‘副作用’是在计算结果的过程中,系统状态的一种变化,或者与外部世界进行可观察的交互。概括来讲,只要跟函数外部环境发生的交互就都是副作用。函数式编程的哲学就是假定副作用是造成不正当行为的主要原因。并不是说,要禁止使用一切副作用,而是,要让他们在可控的范围内发生。从定义上来说,纯函数必须能根据相同的输入返回相同的输出;如果函数需要跟外部事物打交道,那么就无法保证这一点了。意味着函数要与外部系统状态打交道,提倡函数式编程的人认为,这种共享状态导致的混乱是绝大多数bug的万恶之源

    var	xs	=	[1,2,3,4,5];
    //	纯函数
    xs.slice(0,3);
    //=>	[1,2,3]
    xs.slice(0,3);
    //=>	[1,2,3]
    xs.slice(0,3);
    //=>	[1,2,3]
    
    //	非纯函数
    xs.splice(0,3);
    //=>	[1,2,3]
    xs.splice(0,3);
    //=>	[4,5]
    xs.splice(0,3);
    //=>	[]
    //	不纯的
    var minimum = 21;
    var checkAge = function(age) {
    	return age >= minimum;
    };
    //	纯函数
    var checkAge = function(age) {
    	var minimum = 21;
    	return age >= minimum;
    };

    在不纯的版本中,函数的结果取决于 minimum 这个可变变量的值。换句话说,它取决于系统状态。输入值(参数)之外的因素能够左右函数的返回值,会使函数变得不纯,导致我们思考整个软件是总是要面对函数外部复杂多变的系统状态。

    如果一个函数是纯函数,它的输入就直接表明了输出,那么就没有必要实现具体的细节了,因为函数仅仅只是输入到输出的映射。基于这个概念,就可以逐步构建出函数式编程的蓝图。

    传统的命令式编程方法和过程都深深地植根于它们所在的环境中,通过状态、依赖和有效作用达成。而纯函数则与环境无关,可以在任何地方运行它,并保证相同的输入总会有相同的结果。

    #纯函数的好处

    1.引用透明性

    所谓的引用透明性就是一段代码可以替换成它执行所得的结果,而且是在不改变整个程序行为的前提下,替换的。而纯函数就是引用透明的。引用透明意味着可以进行等式推导(就像高中数学的推导),等式推导可以为重构和理解代码带来相当大的分析能力。

    //太傻
    var getServerStuff = function(callback) {
    	return ajaxCall(function(json) {
    		return callback(json);
    	});
    };
    
    //这才像样
    var getServerStuff = ajaxCall;
    
    //因为
    return ajaxCall(function(json) {
    	return callback(json);
    });
    
    //等价于
    return ajaxCall(callback(json));
    
    //而
    var getServerStuff = function(callback) {
    	return ajaxCall(callback(json));
    };
    
    //就等于...
    var getServerStuff = ajaxCall;

    2.并行代码

    纯函数不依赖于系统状态的特点,我们就可以并行运行任意纯函数。因为纯函数根本不需要访问共享的内存,而且根据其定义,纯函数也不会因副作用而进入竞争态。

  • 相关阅读:
    (转载)Android xml资源文件中@、@android:type、@*、?、@+引用写法含义以及区别
    Android事件分发和消费机制(转载)
    Android动画及滑动事件冲突解决(转载)
    写在学习Oracle之前
    laragon yii
    ubuntu使用bower install问题汇总
    LNMP架构下访问php页面出现500错误
    form表单提交无页面刷新(非js)
    Firefox浏览器无法安装插件的解决
    完美解决 Ubuntu 下 Sublime Text 2配置搜狗拼音输入法
  • 原文地址:https://www.cnblogs.com/hwencc/p/5058481.html
Copyright © 2011-2022 走看看