了解函数式编程

了解函数式编程

        前几天看ES6标准入门时,第八章函数。看到了函数式编程,和函数柯里化字眼,想着在以前也没有太多的了解,于是就花了点时间去研究学习了一下,有不对的地方希望大家多多指点。

        百度上是这样的解释的“函数式编程是种编程范式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是 λ演算(lambda calculus)。而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。和指令式编程相比,函数式编程强调函数的计算比指令的执行重要。和过程化编程相比,函数式编程里,函数的计算可随时调用”。简单点来说就是,主要思想是把运算过程尽量写成一系列嵌套的函数调用,进行函数之间传递。下面就从一下几个特性和特征来说明到底什么算是函数式编程。

特性

    高阶函数

          那什么是高阶函数呢?在函数编程中,我们要做的是把函数传来传去,而不是对象式编程那样,将对象传来传去,那么这样的调用形式,我们就叫做高阶函数。比如计算x+y的值

  function bind(fn.context){

      return function(){

               fn.apply(context,arguments);
        }
}

   function func(){}

   bind(func,window)
    惰性计算

         即表达式不是在绑定到变量时立即计算,而是在求求值程序需要产生表达式的值进行计算,比如

       var  sum = function(x,y){
            return x+y;
       }

   递归

            这点想必大家都明白,意思就是函数里面调用自身函数,作为控制流程的机制,比如

       function sum(x){
          if(x == 1 ) return
          return  sum(x*(x-1));
       } 

特征

   没有副作用

        独立性高,函数内的运算不影响全局变量的值,产生运算以外的其他结果。每一次运算都会返回一个新的值,且不收其它函数的影响,比如:

      var arr = [1,2,4,5]
      arr.slice(1);//[2,4,5]
      arr.slice(0);//[1,2,4,5]
   //而以下这样就不行
     var arr = [1,2,4,5]
     arr.splice(0,1)
     console.log(arr) //[2,4,5]
     arr.splice(0,1) 
     console.log(arr) //[4,5]

    不修改状态

         函数式编程只是返回新的值,不修改系统变量,因此不修改变量也是其中一个重要的特点。我们说,函数式编程是无状态的,可是在我们现实情况中,状态不可能一直保持不变,而状态必然需要改变,传递,那么我们在函数式编程中的则是将其保存在函数的参数中,作为函数的附属品来传递。例子如下

      function reverse(string) {
     if(string.length== 0) {
       return string;
      } else {
       returnreverse(string.substring(1, string.length)) + string.substring(0, 1);
     }
      }

   使用声明式而不适用命令式代码

       命令式代码的意思就是,我们通过编写一条又一条指令去让计算机执行一些动作,这其中一般都会涉及到很多繁杂的细节。

        "表达式"(expression)是一个单纯的运算过程,总是有返回值;"语句"(statement)是执行某种操作,没有返回值。函数式编程要求,只使用表达式,不使用语句。也就是说,每一步都是单纯的运算,而且都有返回值。原因是函数式编程的开发动机,一开始就是为了处理运算(computation),不考虑系统的读写(I/O)。"语句"属于对系统的读写操作,所以就被排斥在外,函数式在编程中尽量把I/O限制到了最小,比如以下例子

   //命令式
    var arr = [];
    for(var i = 0; i<oArr.length;i++){
      arr.push(li[i])
    }
   //声明式
   var arr = [];
   var arr = oArr.map(function(item,index,arr){
       return item
   })

  引用透明性

       如果你还记得一些初中的数学知识的话,函数 f的概念就是,对于输入 x 产生一个输出 y = f(x)。这便是一种最简单的纯函数。纯函数的定义是,对于相同的输入,永远会得到相同的输出,而且没有任何可观察的副作用,也不依赖外部环境的状态。

   函数是“一等公民”

     所谓"第一等公民"(first class),指的是函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。

      举例来说,下面代码中的print变量就是一个函数,可以作为另一个函数的参数。

       var print =function(i){ console.log(i);};
       [1,2,3].forEach(print);

  补充:对于高阶高阶函数的这一特性,可以联想到函数柯里化,即思是将多参数的函数转换成单参数的形式,例子 如下

    functioncurry(fn){
      var args = Array.prototype.slice.call(arguments, 1);
      return function(){
           var innerArgs = Array.prototype.slice.call(arguments);
           var finalArgs = args.concat(innerArgs);
           return fn.apply(null, finalArgs);
       };
   }
   functionadd(num1, num2){
     returnnum1 + num2;
   }
   varcurriedAdd = curry(add, 5);
   alert(curriedAdd(3));//8

   实上柯里化是一种“预加载”函数的方法,通过传递较少的参数,得到一个已经记住了这些参数的新函数,某种意义上讲,这是一种对参数的“缓存”,是一种非常高效的编写函数的方法



函数式编程的优点

  1. 代码简洁,开发快速

       函数式编程大量使用函数,减少了代码的重复,因此程序比较短,开发速度较快。

  2 .接近自然语言,易于理解

       函数式编程的自由度很高,可以写出很接近自然语言的代码。

  3. 更方便的代码管理

      函数式编程不依赖、也不会改变外界的状态,只要给定输入参数,返回的结果必定相同。因此,每一个函数都可以被看做独立单元,很有利于进行单元测试(unit testing和除错(debugging),以及模块化组合

  4.代码的热升级

     函数式编程没有副作用,只要保证接口不变,内部实现是外部无关的。所以,可以在运行状态下直接升级代码,不需要重启,也不需要停机.

  5. 易于"并发编程"

      函数式编程不需要考虑"死锁"(deadlock),因为它不修改变量,所以根本不存在"锁"线程的问题。不必担心一个线程的数据,被另一个线程修改,所以可以很放心地把工作分摊到多个线程,部署"并发编程"(concurrency)。Erlang语言早就证明了这一点,它是瑞典爱立信公司为了管理电话系统而开发的,电话系统的升级当然是不能停机的。

    请看下面的代码:

    var s1 =Op1();
    var s2 =Op2();
    var s3 =concat(s1, s2);

     由于s1和s2互不干扰,不会修改变量,谁先执行是无所谓的,所以可以放心地增加线程,把它们分配在两个线程上完成。其他类型的语言就做不到这一点,因为s1可能会修改系统状态,而s2可能会用到这些状态,所以必须保证s2在s1之后运行,自然也就不能部署到其他线程上了。

参考来源:

https://baike.baidu.com/item/%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B/4035031?fr=aladdin

http://www.ruanyifeng.com/blog/2012/04/functional_programming.html

https://zhuanlan.zhihu.com/p/21714695

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值