2015年1月29日 星期四

閉包 Closures - 高階函式 Higher-order functions

func connect(str1 : String, str2 : String) -> String {
    return str1 + " " + str2
}
connect("hello","world") // "hello world"

func say(name : String, function : (String, String) -> String) -> String{
    let greet = "你好"
    var str = function(name, greet)
    return str
}

// 1. 函數被當成變數傳入另一個函數
var result = say("Ian",connect)
println(result) // "Ian 你好"

// 2. 閉包運算式(Closure Expressions
// connect函數的名稱用函數型態取代,in關鍵字之後為程式碼內容。
result = say("Peter", { (str1:String, str2:String) -> String in
    return str1 + " " + str2
})
println(result) // "Peter 你好"

// 3. 根據上下文推斷型態(Inferring Type From Context
result = say("Alex", { str1, str2 in
    return str1 + " " + str2
})
println(result)// "Alex 你好"

// 4. 閉包單行表示式隱含返回(Implicit Return From Single-Expression Clossures
// 拿掉return關鍵字
result = say("Jay", { str1, str2 in str1 + " " + str2 })
println(result) // "Jay 你好"

// 5. 參數名稱縮寫(Shorthand Argument Names
// 直接通過$0,$1,$2...來順序引用閉包的參數
result = say("Alice", { $0 + " " + $1 })
println(result) // "Alice 你好"

// 6. 運算符函數(Operator Functions
// 簡單地傳遞一個加號,Swift可以自動推斷出我們想使用加號的字串函數操作。
result = say("Bob", + )
println(result) // "Bob 你好"

// 尾隨閉包(Trailing Closures
// 把最後一個參數(閉包函數)搬出參數列括弧,整個大括弧搬出小括弧之外。當閉包內容冗長的時候,適合這樣表達。
result = say("Tim"){
    (str1 : String, str2 : String) -> String in return str1 + str2
}
println(result) // "Tim 你好"
======================================

使用 Javascript 的範例,改寫成 Swift 版
http://ianworkshop.blogspot.tw/2014/03/blog-post.html

高階函示 : 
1. 把其他函式當作引數 (callback function / 回呼函式, 即呼叫時傳入她, 然後她再呼叫回來)
2. 會回傳函式

  • 使用標準程式庫原本的方法


// 將陣列中的數值由小到大重新排列
var nums = [1,3,5,7,9,8,6,4,2]

// 2. 閉包運算式
nums.sort({ (n1:Int, n2:Int) -> Bool in
    n1 < n2
})
println(nums)

// 3. 推斷型態
nums.sort({ n1, n2 in
    return n1 < n2
})

// 4. 隱含返回 (拿掉return關鍵字)
nums.sort({ n1, n2 in n1 < n2 })

// 5. 參數名稱縮寫
nums.sort({ $0 < $1 })

// 6. 運算符函數
nums.sort( < )

// 7. 尾隨閉包
nums.sort{ (n1:Int, n2:Int) -> Bool in
    n1 < n2
}

// 尾隨閉包 + 參數名稱縮寫

nums.sort{ $0 < $1 }

======
// 將陣列中的字串都轉為大寫
var names = ["Ian","Peter","Kevin"]
// 尾隨閉包 + 參數名稱縮寫

names = names.map { $0.uppercaseString }
println(names) // "[IAN, PETER, KEVIN]"



  • 自訂高階函式
// 依照條件建立字串
func builderString(n:Int, callback:(counting:Int) -> String ) -> String {
    var result = "";
    for i in 0...n {
        result = result + callback(counting: i)
    }
    return result
}

// 建立 1~9
var digits_1 = builderString(8, { (counting) -> String in
    return "\(counting+1)"
})

var digits_2 = builderString(8) { "\($0+1)"}

沒有留言: