swift 之函数式编程(一)

1. 什么是函数式编程?python

函数式编程是阿隆佐思想的在现实世界中的实现, 它将电脑运算视为数学上的函数计算,而且避免使用程序状态以及异变物件。 函数式编程的最重要基础是λ演算。并且λ演算的函數能够接受函數當做輸入(引數)和輸出(傳出值),函數式編程更加強調程序执行的结果而非执行的过程,倡导利用若干简单的执行单元让计算结果不断渐进,逐层推导复杂的运算,而不是设计一个复杂的执行过程。函数式编程的杀手锏正是当今世界上日益增加的并行性编程和元数据编程趋势。其主要思想就是把运算过程尽可能写成一系列嵌套的函数调用git

2. 函数式编程的特色:程序员

  • 函数是“第一等公民”:函数与其余数据类型同样,处于平等地位,能够赋值给其余变量,也能够做为参数,传入另外一个函数,或者做为别的函数的返回值
  • 只用“表达式”,不用语句:“表达式”--是一个单纯的运算过程,老是有返回值; ‘语句’--执行某种操做,没有返回值。函数式编程要求,只用表达式,不使用语句,也就是说,每一步都是单纯的运算,并且没有返回值。但在实际的I/O是不可能的,所以,编程过程当中,函数式编程只要求把I/O限制到最小,不要有没必要要的读写行为,保持计算过程的单纯性。
  • 没有反作用:函数要保持独立,全部的功能就是返回一个新的值,没有其余行为,尤为是不得修改外部变量的值
  • 不修改状态: 函数式编程只是返回新的值,不修改系统变量。
  • 引用透明: 函数的运行不依赖于外部变量或"状态",只依赖于输入的参数,任什么时候候只要参数相同,引用函数所获得的返回值老是相同的

3.入手一门新的语言的 时候,通常关注的内容有:
1.原生的数据结构
2.运算符
3.分支控制
4.若是是面向对象的编程语言,其面向对象的实现是怎样的
5.若是是函数式编程语言,其面向函数式编程的实现是怎么样的
6.若是是面向接口的编程语言,器面向接口是如何实现的
7.若是是支持泛型编程,那么又是如何实现的
 
 
4.对于支持函数式编程的语言,其通常的特色可能包含如下几种:
1. 支持递归
2. 函数自己是语言First Class 的组成要素,且支持高阶函数和闭包
3. 函数调用尽量没有反作用(Side Effect)的条件 
    前面的一、2 swift是毋庸置疑的。对于条件3:
    为了减小函数的反作用,不少函数式编程语言都力求达到所谓的“纯函数”。纯函数是指函数与外界交换数据的惟一渠道是 参数和返回值,而不会受到外部变         量的干扰。这彷佛是跟闭包的概念相抵触。由于闭包自己的一个重要的特色就是能够访问到函数定义时的上下文环境。由于闭包自己的一个重要的特色就是能够       访问到函数定义时的上下文环境。
           事实上,为了支持这种状况下的纯函数,一些编程语言提供的数据结构式不可变的(Persist)。好比说,在 Python 中,字符串 str就是一类不可变的数据       结构。 你不能在原来的字符串上进行修改,每次想要进行相似的操做,其实都是生成了一个新的 str对象。 然而 Python 中的链表结构则是可变的。
a = "hello ,"
b = a 
a += 'world'
print a   # hello ,world
print b   # hello ,

    swift中更多的是值类型,而不是引用类型,你会发现Int,Float,String,Array,Dictionary等都是Struct类型,而Struct都是值类型【暗示告终构体应该主要         用于封装数据】,固然Enum也是值类型github

     在swift中区分值类型和引用类型是为了将可变和不可不区分开来。值类型的数据传递给函数,函数内部能够自由拷贝,改变值,而不用担忧产生反作用。在多线      程环境下,多个线程同时运行,可能会意外错误地修改数据,这经常会是一种难以调试的bug。而使用值类型,你能够安全地在线程间传递数据,由于值类型传递      是拷贝,因此无需在线程间同步数据变化。这就能够保证代码线程环境下的安全性。编程

     swift中的参数定义中加入inout,这样的话就能够经过参数来修改变量。这个特性颇有C的风格。swift

     使用swift自带的数据结构并不能很好的的实现“无反作用”的“纯函数式”编程。幸亏做为一种关注度很高的语言, 已经有开发者为其实现了一套彻底知足不可变要      求的数据结构和库:Swiftz。坚持使用let和swiftz提供的数据结构来操做,就能够实现“纯函数式”编程。数组

     不变性有诸多好处安全

  • 更高层次的抽象。程序员能够以更接近数学的方式思考问题。数据结构

  • 更容易理解的代码。因为不存在反作用,不管多少次执行,相同的输入就意味着相同的输出。纯函数比有可变状态的函数和对象理解起来要容易简单得多。你无需再担忧对象的某个状态的改变,会对它的某个行为(函数)产生影响。多线程

  • 线程安全的代码。这意味着多线程环境下,运行代码没有同步问题。它们也不可能由于异常的发生而处于没法预测的状态中。

惰性求值

惰性计算是函数式编程语言的一个特性。惰性计算的表达式不在它被绑定到变量以后就当即求值,而是在该值被取用的时候求值。惰性计算有以下优势。

  • 首先,你能够用它们来建立无限序列这样一种数据类型。由于直到须要时才会计算值,这样就可使用惰性集合模拟无限序列。
  • 第二,减小了存储空间。由于在真正须要时才会发生计算。因此,节约了没必要要的存储空间。
  • 第三,减小计算量,产生更高效的代码。由于在真正须要时才会发生计算。因此,节约那部分没有使用到的值的计算时间。例如,寻找数组中第一个符合某个条件的值。找到了以后,数组里该值以后的值均可以没必要计算了。
func doSomeWork(optional:Int?,defaultValue:Int)->Int{
    if let opt = optional{
        return opt
    }else{
        return defaultValue
    }
}

func doSomeWorkNew(optional:Int?, defaultValue:()->Int)->Int{
    
    if let opt = optional{
        return opt
    }else{
        return defaultValue()
    }
}

let value:Int? = 1
doSomeWork(value, (2+5))
doSomeWorkNew(value, { () -> Int in
    return 2+5
})

上面的代码能够感受到惰性求值的好处。

swift也提供了支持惰性求值的语法:下面展现了将默认是严格求值的数组变为惰性序列:

let r = 1...3
let seq = lazy(r).map {
    (i: Int) -> Int in
    println("mapping \(i)")
    return i * 2
}

for i in seq {
    println(i)
}

 

      Swift对函数式编程的支持,使得程序员多了一种选择。Swift并不强迫程序员必定要以面向对象的方法思惟。在场景合适的状况下,程序员能够选择使用函数式风格编写代码。若是确实是合适的场景,就可以改善生产力。现实的选择是支持面向对象编程的同时,提供函数式的支持。这样,在大部分面向对象游刃有余的地方,仍然可使用面向对象的方法。而在适合函数式编程的地方,而你又拥有函数式编程的思惟和能力时,还能够采用函数式的编程方法改善生产力。

 

接下来的系列文章中我将以《Functional Programing in Swift》这本书,来一块儿学习swift的函数式编程。

相关文章
相关标签/搜索