swift函数式编程日记

map,一一遍历处理,映射为一个新的数组
filter,选出条件判断返回值为true的元素

//MARK: 函数式编程
var arr = [1,2,3,4]

var arr1 = arr.map { i in
    i * 2
}
//等价于
var arr2 = arr.map { $0*2 }
//map,一一遍历处理,映射为一个新的数组
print(arr1,arr2)
//[2,4,6,8][2,4,6,8]

//筛选,选出返回值为true的
var arr3 = arr.filter { $0%2 == 0 }
print(arr3)
//[2,4]

@inlinable public func reduce(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result
第一个参数,传入一个初始化的结果,第二个参数为 两个参数的闭包(result,element),其中第一个参数有初始化值(第一次进入遍历的时候)为该方法的第一个参数initialResult,第二个参数为遍历数组元素,第二次遍历的时候Result的值为第一次遍历返回的值。第一次遍历结果为0x2+1 = 1,第二次遍历结果为1x2+2 = 4

var arr4 = arr.reduce(0) {$0 * 2 + $1}
//等价于
arr4 = arr.reduce(0, { partialResult, i in
    print(partialResult,i)
    return partialResult * 2 + i
})
//    @inlinable public func reduce(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result
//第一个参数,传入一个初始化的结果,第二个参数为  两个参数的闭包(result,element),其中闭包的第一个参数有初始化值(第一次进入遍历的时候)为该方法的第一个参数initialResult,第二个参数为遍历数组元素,第二次遍历的时候Result的值为第一次遍历返回的值。第一次遍历结果为0x2+1 = 1,第二次遍历结果为1x2+2 = 4

print(arr4,"9999999")
//0 1
//1 2
//4 3
//11 4
//26 9999999

flatMap:见代码

var arr5 = arr.map { Array.init(repeating: $0, count: $0) }
var arr6 = arr.flatMap { Array.init(repeating:$0,count:$0) }
print(arr5)
print(arr6)
//[[1], [2, 2], [3, 3, 3], [4, 4, 4, 4]]
//[1, 2, 2, 3, 3, 3, 4, 4, 4, 4]

lazy.map是用到哪个值的时候才会遍历计算哪个值

//lazy.map是用到哪个值的时候才会遍历计算哪个值
let result = arr.lazy.map {
    (i: Int) -> Int in
    print("mapping \(i)")
    return i * 2
}
print("begin-----")
print("mapped", result[0])
print("mapped", result[1])
print("mapped", result[2])
print("end----")
//begin-----
//mapping 1
//mapped 2
//mapping 2
//mapped 4
//mapping 3
//mapped 6
//end----

Optional的map 和flatMap
Optional(可选型)的map和flatMap返回值都为可选型,为nil时,返回值为nil,如果返回值又被包了一个可选型,那么map原样返回,为一个可选型的可选型,但flatMap不再进行包装(可以理解为它比较智能,已经是可选型了就不再包装了)

var num: Int? = 10
var num1 = num.map { $0*2 }
var num2: Int? = nil
var num3 = num2.map { $0*2 }
print(num1,num2,num3)
//Optional(20) nil nil
var num4 = num2.flatMap { $0*2 }
var num5 = num.flatMap { $0*2 }
print(num4,num5)
//nil Optional(20)

var num6 = num.map { Optional.some($0*2) }
var num7 = num.flatMap { Optional.some($0*2) }
print(num6,num7)
//Optional(Optional(20)) Optional(20)

//可选型和整型相加
var num8 = (num != nil) ? (num! + 10) : nil//如果num不为nil 强制解包+10 如果为nil设置为nil
//等价
var num9 = num.map { $0 + 10 }
print(num8,num9)
//Optional(20) Optional(20)


//练习使用
var fmt = DateFormatter()
fmt.dateFormat = "yyyy-MM-dd"
var str:String? = "2011-09-10"
var date1 = str != nil ? fmt.date(from: str!) : nil
//等价
var date2 = str.flatMap { fmt.date(from:$0) }
print(date1,date2)
//Optional(2011-09-09 16:00:00 +0000) Optional(2011-09-09 16:00:00 +0000)

var score: String? = "90"
//old
var score1 = score != nil ? "score is \(score)" : "no score"
//new
var score2 = score.map { "score is \($0)" } ?? "no score"
print(score1, score2)
//score is Optional("90")  score is 90


struct Person {
    var name: String
    var age: Int
}
var items = [
    Person(name: "jack", age: 20),
    Person(name: "rose", age: 21),
    Person(name: "kate", age: 22) ]
// old
func getPerson1(_ name: String) -> Person? {
    let index = items.firstIndex { $0.name == name }
    return index != nil ? items[index!] : nil
}
// new
func getPerson2(_ name: String) -> Person? {
    return items.firstIndex {$0.name == name }.map { items[$0] }
 /* items.firstIndex遍历到符合条件的第一个元素就停止,并返回下标*/
/* map { items[$0] }把上一个函数的返回值传到map,相当于index.map{items[$0]}*/
}
struct Person {
    var name: String
    var age: Int
    init?(_ json: [String : Any]) {
    guard let name = json["name"] as? String,
    let age = json["age"] as? Int else {
    return nil
    }
    self.name = name
    self.age = age
    }
}
var json:Dictionary? = ["name":"jack","age":10]
//old
var p1 = json != nil ? Person.init(json!) : nil
//new
var p2 = json.flatMap { Person.init($0) }

函数式编程(Funtional Programming)

// 假设要实现以下功能:[(num + 3) * 5 - 1] % 10 / 2
var num = 1

传统写法

func add(_ v1: Int, _ v2: Int) -> Int { v1 + v2 }
func sub(_ v1: Int, _ v2: Int) -> Int { v1 - v2 }
func multiple(_ v1: Int, _ v2: Int) -> Int { v1 * v2 }
func divide(_ v1: Int, _ v2: Int) -> Int { v1 / v2 }
func mod(_ v1: Int, _ v2: Int) -> Int { v1 % v2 }
divide(mod(sub(multiple(add(num, 3), 5),1),10),2)

函数式写法

func add(_ v1:Int) -> (Int) -> Int {
    return {
        v2 in
        return v2 + v1
    }
}
//可简写为
func add(_ v1:Int) -> (Int) -> Int { { $0 + v1 } }
//手动柯里化(currying),把多个参数的函数,变成只有一个参数的函数,并返回另一个函数。
//其中上边复杂写法v2为返回的函数的参数,即可简写为$0,缩写为一行,即为简写的。
//let fn = add(3),那么fn就是一个+3的函数,然后调用fn(num),就是add(3)(num),等价为num + 3
//同理
func sub(_ v1: Int) -> (Int) -> Int { { $0 - v1 } }
func multiple(_ v1: Int) -> (Int) -> Int { { $0 * v1 } }
func divide(_ v1: Int) -> (Int) -> Int { { $0 / v1 } }
func mod(_ v1: Int) -> (Int) -> Int { { $0 % v1} }

//把连个函数合并成一个函数
func hebing(_ f1:@escaping(A) -> B,_ f2:@escaping(B) -> C) -> (A) -> C {
    return { a  in
       return f2(f1(a))
    }
}

//等价于:自定义运算符
infix operator >>> : AdditionPrecedence //调用为 f1 >>> f2
func  >>>(_ f1:@escaping (A) -> B,_ f2:@escaping (B) -> C) -> (A) -> C  {
    { f2(f1($0)) }
}
let fn1 = hebing(hebing(hebing(hebing(add(3), multiple(5)), sub(1)) , mod(10)), divide(2))
let fn = add(3) >>> multiple(5) >>> sub(1) >>> mod(10) >>> divide(2)

print(fn(num),fn1(num))
//4 4

拓展:自定义运算符

prefix operator 前缀运算符 对象前跟这个运算符 比如 -2
postfix operator 后缀运算符 比如num--
infix operator 中缀运算符 : 优先级组 1+2
precedencegroup 优先级组 {
associativity: 结合性(left\right\none)
higherThan: 比谁的优先级高
lowerThan: 比谁的优先级低
assignment: true代表在可选链操作中拥有跟赋值运算符一样的优先级
}

柯里化

什么是柯里化?
a、将一个接受多参数的函数变换为一系列只接受单个参数的函数。
Array、Optional的map方法接收的参数就是一个柯里化函数

func add(_ v1: Int, _ v2: Int) -> Int { v1 + v2 }
add(10,20)
//柯里化
func add(_ v1:Int) -> (Int) -> Int { { $0 + v1 } }
add(10)(20)
//将一个多参函数变成一个柯里化后的函数

func add1(_ v1: Int, _ v2: Int) -> Int { v1 + v2 }
func add2(_ v1: Int, _ v2: Int, _ v3: Int) -> Int { v1 + v2 + v3 }

func currying1 (_ f1:@escaping (A,B) -> C) -> (A) -> (B) -> C {
//将一个有 A类型,B类型两个参数返回C类型参数的函数,变成 一个只有A参数返回 只有一个B参数返回C参数的函数
    return {
       a in
        return {
            b in
            return f1(a,b)
        }
    }
}
//等价于
func currying2 (_ f1:@escaping (A,B) -> C) -> (A) -> (B) -> C {
    {a in {b in f1(a,b )} }
}
//等价于
//prefix func ~ (_ f1:@escaping (A,B) -> C) -> (A) -> (B) -> C {
//    {a in {b in f1(a,b )} }
//}
//同理
func currying(_ fn: @escaping (A, B, C) -> D) -> (A) -> (B) -> (C) -> D {
{ a in { b in { c in fn(a, b, c) } } }
}
//等价于
prefix func ~(_ fn: @escaping (A, B, C) -> D) -> (A) -> (B) -> (C) -> D {
{ a in { b in { c in fn(a, b, c) } } }}
let curryingAdd1 = currying1(add1)
print(curryingAdd1(2)(6))
//8
let curryingAdd2 = currying(add2)
print(curryingAdd2(1)(2)(3))
//6
//var fn = (~add)(3) >>> (~multiple)(5) >>> (~sub)(1) >>> (~mod)(10) >>> (~divide)(2) //不用手动柯里化原来的函数就可以add(3) >>> multiple(5) >>> sub(1) >>> mod(10) >>> divide(2)
//fn(num)

溢出运算符

var min = UInt8.min//0
print(min,min - 1)
print(min,min &- 1)//0,255, (Int8.max),如果直接打印min - 1的话会直接闪退
//这时候提供溢出运算符&- 相当于转一圈回去。

运算符重载

类、结构体、枚举可以为现有的运算符提供自定义的实现,这个操作叫做:运算符重载
struct Point {
    var x:Int,y:Int
}
func + (p1:Point,p2:Point) -> Point {
    return Point.init(x: p1.x + p2.x, y: p1.y + p2.y)
}
let p1 = Point.init(x: 1, y: 2)
let p2 = Point.init(x: 3, y: 4)
let p3 = p1 + p2

print(p3)
//Point(x: 4, y: 6)

你可能感兴趣的:(swift函数式编程日记)