首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >通过Swift学函数式编程

通过Swift学函数式编程

作者头像
刘笑江
发布2018-05-28 13:39:41
7162
发布2018-05-28 13:39:41
举报
文章被收录于专栏:刘笑江的专栏刘笑江的专栏

在文章SWIFT IS A LOT LIKE SCALA [1] 提到Swift和Scala有很大的相似之处,在某些特性甚至比Scala对函数式编程的支持更友好。笔者遂从Swift语言出发,学习函数式编程[2] [3],并记录笔记如下。

什么是函式编程

是一种编程范式,强调数学化的函数,不可变(immutable),expressiveness,尽量少地使用变量、状态。

由这些特性带来的好处有:解耦,使App易于测试,易于并发、并行化。

Map Reduce Filter

Array Filter

这些函式方法和Python很像,例子:

func isEven(number: Int) -> Bool {
    return number % 2 == 0
}

// First-class function, 函数作为变量看待
let evens1 = Array(1...10).filter(isEven)
println(evens1)

// Closure 闭包,匿名函数,即Python里面的Lambda
let evens2 = Array(1...10).filter{
    (number) in
    number % 2 == 0
}

自制Filter

此处自定义了一个泛型函数Generic Function。

func myFilter<T>(source: [T], predicate:(T) -> Bool) -> [T] {
    var result = [T]()
    for i in source {
        if predicate(i) {
            result.append(i)
        }
    }
    return result
}

Array Reduce

任务:取1…10的偶数求和

let evenSum = Array(1...10)
    .filter { (number) in number % 2 == 0 }
    .reduce(0) { (total, number) in total + number }

或者简写

let evenSum = Array(1...10)
    .filter { $0 % 2 == 0 }
    .reduce(0) { $0 + $1 }    

println(evenSum)

自定义Reduce

extension Array {
    func myReduce<T,U>(seed:U, combiner:(U,T)->U) -> U 
    {
    var cur = seed
    for item in self {
        cur = combiner(cur, item as T)
    }
    return cur
}

let evenSum = Array(1...10)
    .filter { (number) in number % 2 == 0 }
    .myReduce(0) { (total, number) in total + number }

println(evenSum)

递归Reduce

需先声明Closure类型,再定义行为。参考Advanced Swift at WWDC14 [4] 的视频。

let list: ArraySlice = [1,2,3,4,5,6,7,8,9,10]
var closure:((Int, ArraySlice<Int>) -> Int)!
closure = { (memo, list) in
    if (list.count == 0) {
        closure = nil // remove retain cycle
        return memo
    } else {
        return closure(memo + list[0], list[1..<list.count])
    }
}

let value = closure(0, list)

函数式编程练习:建立字典索引

输入如:

let words = ["Guinea Pig", "Mouse", "Monkey", "Fish", "Dog", "cat", "chicken"]

求输出:

let dict = [(C, [Cat, Chicken]),
            (F, [fish]),
            (D, [Dog]),
            (M, [Mouse, monkey]),    
            (G, [Guinea Pig])]

思路1:

extension String {
    subscript (i: Int) -> Character {
        return self[advance(self.startIndex, i)]
    }
    func firstCharacter() -> Character {
        return self[0] as Character
    }
}

typealias WordList = [String]
typealias Entry = (Character, WordList)
typealias Entries = Array<Entry>

func buildIndexOf(words: WordList) -> Entries {
    return words
        .reduce(Entries()) { (entries, word) in
            // 1
            // for each word in words
            // check if word.firstChar in entries
            for entry: Entry in entries as Entries {
                let char: Character = entry.0
                let word_list: WordList = entry.1
                // 2
                // Indexed char: add word to word_list
                if char == word.uppercaseString.firstCharacter() {
                    let new_entry = Entry(char, word_list + [word])
                    // immutable entries, need to create new by append
                    return entries.filter() {$0.0 != char } + [new_entry]
                }
            }
            // 3
            // Unindexed char: create Entry
            let entry: Entry = Entry(word.uppercaseString.firstCharacter(), [word])
            return entries + [entry]
        }
}

let words = ["Guinea Pig", "Mouse", "Monkey",
    "Fish", "Dog", "cat", "chicken"]
println(buildIndexOf(words))

思路2:(参见[2] )

func buildIndexOf(words: WordList) -> Entries {
    let distinctIndex: [Character] = words.reduce([Character]()) {
        (char, word) in
        if !contains(char, word.uppercaseString.firstCharacter()) {
            return char + [word.uppercaseString.firstCharacter()]
        }
        return char
    }
    // distinctIndex = ['A','F','G',...]

    // add word into index
    let entries: Entries = distinctIndex.map {
        char -> Entry in // -> Entry
        return Entry(char, words.filter() { char == $0.uppercaseString.firstCharacter() })
    }
    return entries
}

let words = ["Guinea Pig", "Mouse", "Monkey",
    "Fish", "Dog", "cat", "chicken"]

println(buildIndexOf(words))

尾递归 Tail-Recursion


  1. http://leverich.github.io/swiftislikescala/ ↩︎
  2. http://www.raywenderlich.com/82599/swift-functional-programming-tutorial ↩︎
  3. http://jamesonquave.com/blog/functional-programming-in-swift/ ↩︎
  4. https://developer.apple.com/videos/wwdc/2014/#404 ↩︎
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015-05-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是函式编程
  • Map Reduce Filter
    • Array Filter
      • 自制Filter
        • Array Reduce
          • 自定义Reduce
            • 递归Reduce
            • 函数式编程练习:建立字典索引
            • 尾递归 Tail-Recursion
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档