zoukankan      html  css  js  c++  java
  • 第一章 什么是函数式编程

    第一章 什么是函数式编程

    一.前言

    1. 函数式编程:使用纯函数来构造程序。
      (1)纯函数是没有副作用的函数。
      (2)副作用是指,函数执行过后,不仅有返回值,与此同时,还进行了其他操作:
          (a) 修改了其他变量的值
          (b) 设置了对象的属性
          (c) 抛出了一个异常,或以一个错误终止
          (d) 打印到终端,或获取用户键盘输入
          (e) 读取或写入一个文件
    2. 纯函数的优势
      (1)纯函数是模块化的,容易被测试,复用,并行化,泛华,推导。因此纯函数降低了bug出生的概率
      (2)纯函数限制了怎样写程序,而非限制表达什么样的程序。就是说,纯函数依然能进行IO操作,循环改变变量等

    二. 函数式程序对副作用的改造

    1. 第一个程序
        class Cafe{
          def buyCoffee(cc:CreditCard) : Coffee = {
            val cup = new Coffee()
            cc.charge(cup.price)   // 这段代码出现副作用:
            cup 
          }
        }
        ```
    (1)函数只是为了返回一个Coffee对象,而在此过程中,却涉及到了CreditCard对象的更改。因此产生副作用,这个副作用使得代码难以测试,因为信用卡计费更改操作可能是一个webservice,而我们在测试中并不真的想联系信用卡公司
    (2)因此,我们传递一个Payments对象给函数,使代码更加模块化
    
        
    
    
    2. 第2个程序
        ```
        class Cafe{
          def buyCoffee(cc:CreditCard,p:Payments) : Coffee = {
            val cup = new Coffee()
            p.charge(cc,cup.price)   // 这段代码出现副作用:
            cup 
          }
        }
        ```
    (1)改进后的优点:虽然payments的实现可能还是需要调用远程webservice,但是测试代码时,可以使用mock创造一个不用远程调用的接口
    (2)仍然存在的缺点:如果想买12杯咖啡,需要对函数循环12次,这样会进入12次计费计算过程,会导致效率急剧下降。;
    
    
    3. 函数式的代码写法
        ```
        class Cafe{
          def buyCoffee(cc:CreditCard) : (Coffee,Charge) = {
            val cup = new Coffee()
            // p.charge(cc,cup.price)   删除这段
            (cup,Charge(cc,cup.price)) 
          }
          def buyCoffees(cc:CreditCard,n:Int):(List[Coffee],Charge) = {
            val purchases:List[(Coffee,Charge)] = List.fill(n)(buyCoffee(cc))
            val (coffees,charges) = purchases.unzip(coffees,charges.reduce( (c1,c2)=>c1.add(c2) ))
          }
        }
        
        case class Charge(cc:CreditCard,amount:Double){
          def add(other:Charge):Charge = {  // 累计计费,只能累计一个卡
            if(cc==other.cc)
              Charge(cc,amount+other.amount)
            else
              throw new Exception("can't add different cards")
          }
        }
        ```
    【注】:函数式程序的标准写法:纯内核 + 很薄的外壳
    
    
    ####三. 纯函数究竟是什么
    1. `引用透明`:所谓引用透明的概念,就是指一个表达式,这个表达式在程序中可以被他的结果所取代,而不改变程序的含义
    2. `纯函数`:我们利用引用透明的概念定义了纯函数:
                  假设存在一个函数$f$和一个引用透明的表达式$x$,若表达式$f(x)$对所有引用透明的表达式$x$也是引用透明的,那么$f$是一个纯函数
    3. 非纯函数,往往会破坏`引用透明`,使同一个表达式产生的结果并不相同,使人费解
    (eg:1+1表达式永远为2,这就是引用透明,但有些java函数,并不是引用透明的,例如stringbuilder的相关方法)
    
        ```scala
        scala> val x = new StringBuilder("Hello")
        x: StringBuilder = Hello
        
        scala> val r1 = x.append(" world")
        r1: StringBuilder = Hello world
        
        scala> val r2 = x.append(" world")   // r2和r1的表达式一样,但是得到的结果却不同
        r2: StringBuilder = Hello world world
        ```
  • 相关阅读:
    hdu 1258 DFS
    hdu2488 dfs
    poj1915 BFS
    hdu1372 BFS求最短路径长度
    poj3264 线段树
    hdu 2438Turn the corner 三分
    hdu3714 三分
    【转载】单点登陆
    ajax从入门到深入精通
    Web前端技术体系大全搜索
  • 原文地址:https://www.cnblogs.com/moonlord/p/6273141.html
Copyright © 2011-2022 走看看