[连载]Swift开发入门(06)

面向对象编程和函数式编程是目前最主流的两种编程范式,而关于这两种范式孰优孰劣的讨论一直都没有停止过。事实上,真正理解两种编程范式的程序员不会武断的说这二者孰优孰劣,因为任何编程语言都没有什么灵丹妙药让其使用者成为优秀的程序员。其实,像Java这样很经典的面向对象的编程语言,也能够看到函数式编程的影子,如果你使用过访问者模式、命令模式,如果你使用过接口回调,你实际上已经使用了函数式编程的理念,而且在新版本的Java中,已经开始支持Lambda表达式和函数式接口,这些都是Java为了支持函数式编程所作出的改进。同样,,我们也可以用C语言写出面向对象风格的代码。其实,只要在适当的地方使用适当的编程范式就能够写出优质的代码,我们不应该让自己的程序囿于某一种编程范式,就如同一个优秀的程序员绝不会声称自己效忠于某种语言(有很多蹩脚的三流程序员就会做这样的事情)。

简单数组过滤

让我们看这样一个例子,在一个数组中放入一组偶数,传统的做法是这样的。

var evens = [Int]()for i in 1…10 {if i % 2 == 0 {evens.append(i)}}println(evens)// [2, 4, 6, 8, 10]

如果用函数编程的方式,我们可以用下面的代码来做同样的事情。而且我们将判断偶数的代码写成一个函数,明显增加了代码的可重用性。

func isEven(number: Int) -> Bool {return number % 2 == 0}var evens = Array(1…10).filter(isEven)println(evens)

当然,也可以写成下面的样子。

var evens = Array(1…10).filter{ $0 % 2 == 0 }println(evens)// [2, 4, 6, 8, 10]

明显,函数式编程有如下一些特性: – 高阶函数:函数可以作为函数的参数传给函数。 – 一等公民:可以将函数视为变量来使用。 – 闭包:可以使用匿名函数。

归约(Reducing)

如果要在上面的例子再增加一项功能,将数组中的偶数求和,传统的做法如下所示。

var evens = [Int]()for i in 1…10 {if i % 2 == 0 {evens.append(i)}}var evenSum = 0for i in evens {evenSum += i}println(evenSum) // 30

用函数式编程的方式重新编写上面的代码,如下所示。

var evenSum = Array(1…10).filter { $0 % 2 == 0}.reduce(0) { $0 + $1 }println(evenSum) // 30

如果想理解reduce是如何工作的,可以看看函数的原型。

func reduce<U>(initial: U, combine: @noescape (U, T) -> U) -> U索引器

我们再来完成一个新的任务,为数组中的元素建立索引。假如有一个数组中有一系列的字符串,我们希望通过字符串的首字母作为索引来建立一个新的存储结构,传统的做法如下所示。

import Foundationlet words = [“Cat”, “Chicken”, “Fish”, “Dog”, “Mouse”, “Pig”, “Monkey”]typealias Entry = (Character, [String])func buildIndex(words: [String]) -> [Entry] {var result = [Entry]()var letters = [Character]()for word in words {let firstLetter = Character(word.substringToIndex(advance(word.startIndex, 1)).uppercaseString)if !contains(letters, firstLetter) {letters.append(firstLetter)}}for letter in letters {var wordsForLetter = [String]()for word in words {let firstLetter = Character(word.substringToIndex(advance(word.startIndex, 1)).uppercaseString)if firstLetter == letter {wordsForLetter.append(word)}}result.append((letter, wordsForLetter))}return result}// [(“C”, [“Cat”, “Chicken”]), (“F”, [“Fish”]), (“D”, [“Dog”]), (“M”, [“Mouse”, “Monkey”]), (“P”, [“Pig”])]println(buildIndex(words))

使用函数式编程,可以将代码改写为如下所示的样子。

import Foundationlet words = [“Cat”, “Chicken”, “Fish”, “Dog”, “Mouse”, “Pig”, “Monkey”]typealias Entry = (Character, [String])func distinct<T: Equatable>(source: [T]) -> [T] {var unique = [T]()for item in source {if !contains(unique, item) {unique.append(item)}}return unique}func buildIndex(words: [String]) -> [Entry] {func firstLetter(str: String) -> Character {return Character(str.substringToIndex(advance(str.startIndex, 1)).uppercaseString)}return distinct(words.map(firstLetter)).map {(letter) -> Entry in return (letter, words.filter {firstLetter($0) == letter})}}println(buildIndex(words))柯里化(currying)那我想明天可以是我的来世。

[连载]Swift开发入门(06)

相关文章:

你感兴趣的文章:

标签云: