【Swift】#23 關於 Function 與 Closure 的那些小事
Function
Parameter labels
func sayHello(to name: String) {
print("Hello, \(name)!")
}
// 有外部名時,用外部名呼叫
sayHello(to: "Ewen") // Hello, Ewen!
func greet(_ person: String) {
print("Hello, \(person)!")
}
// 用 _ 省略外部名,呼叫就不用寫參數
greet("Ewen") // Hello, Ewen!
Default parameters
func greet(_ person: String, nicely: Bool = true) {
if nicely == true {
print("\(person)\(person)第一名")
} else {
print("\(person)退散")
}
}greet("戴資穎") // 戴資穎戴資穎第一名
greet("酸民", nicely: false) // 酸民退散
Variadic functions
func square(numbers: Int...) {
for number in numbers {
print("\(number)的平方是\(number * number)")
}
}square(numbers: 1, 2, 3, 4, 5)
/*
1的平方是1
2的平方是4
3的平方是9
4的平方是16
5的平方是25
*/
Writing throwing functions
enum PasswordError: Error {
case obvious
}func checkPassword(_ password: String) throws -> Bool {
if password == "password" {
throw PasswordError.obvious
}
return true
}// 執行 throwing functions
do {
try checkPassword("password")
print("可以用這組密碼")} catch {
print("不能用\"password\"當密碼")
}// 不能用"password"當密碼
inout parameters
func doubleInPlace(number: inout Int) {
number *= 2
}
var myNum = 10
doubleInPlace(number: &myNum)print(myNum) // 20
function 當參數
無參數、無回傳值 function 當作參數
func orderAndDrink(upgrade: () -> Void) {
print("今晚我想來點:")
upgrade()
}func addIngredient() {
print("厚奶蓋和寒天蒟蒻")
}orderAndDrink(upgrade: addIngredient)/*
今晚我想來點:
厚奶蓋和寒天蒟蒻
*/
有單一參數、無回傳值 function 當作參數
func orderAndDrink(upgrade: (String) -> Void) {
print("今晚我想來點:")
upgrade("蘋果紅茶")
}func addIngredient(name: String) -> Void {
print("\(name)加厚奶蓋和寒天蒟蒻")
}
orderAndDrink(upgrade: addIngredient)/*
今晚我想來點:
蘋果紅茶加厚奶蓋和寒天蒟蒻
*/
有單一參數、有回傳值 function 當作參數
func orderAndDrink(upgrade: (String) -> String){
print("今晚我想來點:")
let message = upgrade("蘋果紅茶")
print(message)
}func addIngredient(name: String) -> String {
return "\(name)加厚奶蓋和寒天蒟蒻"
}
orderAndDrink(upgrade: addIngredient)/*
今晚我想來點:
蘋果紅茶加厚奶蓋和寒天蒟蒻
*/
function 回傳 function
// order() 回傳有一個 String 型別參數的 function,該 function 無回傳值func drink(name: String) -> Void {
print("\(name)加厚奶蓋和寒天蒟蒻")
}func order() -> (String) -> Void {
print("今晚我想來點")
return drink
}// 法一
let message = order()
message("蘋果紅茶")// 法二(也可以但不推薦)
let message2: Void = order()("蘋果紅茶")/*
今晚我想來點:
蘋果紅茶加厚奶蓋和寒天蒟蒻,正常微冰
*/
Nested function Capturing
func add(adjective: String) -> (String) -> String {
var superString = "超級"
func createSentence(name: String) -> String {
let message = superString + adjective + name
superString += "超級"
return message
}
return createSentence
}let goodMessage = add(adjective: "可愛的")
print(goodMessage("資穎"))
print(goodMessage("資穎"))let badMessage = add(adjective: "可惡的")
print(badMessage("酸民"))
print(badMessage("酸民"))/*
超級可愛的資穎
超級超級可愛的資穎
超級可惡的酸民
超級超級可惡的酸民
*/
Closure
Closure 呼叫
無參數、無回傳值 closure 呼叫
let addIngredient = {
print("加厚奶蓋和寒天蒟蒻")
}addIngredient() // 加厚奶蓋和寒天蒟蒻
有單一參數、無回傳值 closure 呼叫
let addIngredient = { (name: String) in
print("\(name)加厚奶蓋和寒天蒟蒻")
}addIngredient("蘋果紅茶") // 蘋果紅茶加厚奶蓋和寒天蒟蒻
有單一參數、有回傳值 closure 呼叫
let addIngredient = { (name: String) -> String in
return "\(name)加厚奶蓋和寒天蒟蒻"
}let message = addIngredient("蘋果紅茶")
print(message) // 蘋果紅茶加厚奶蓋和寒天蒟蒻
Closure 當參數
無參數、無回傳值 closure 當作參數
func orderAndDrink(upgrade: () -> Void) {
print("今晚我想來點:")
upgrade()
}
// 法一
let addIngredient = {
print("厚奶蓋和寒天蒟蒻")
}
orderAndDrink(upgrade: addIngredient)
// 法二: Trailing closure - 省略代表 closure 的那個參數。之後都用這個語法。
orderAndDrink() {
print("厚奶蓋和寒天蒟蒻")
}/*
今晚我想來點:
厚奶蓋和寒天蒟蒻
*/
【續】若剩 closure 是參數,可以把呼叫它的的函式的括號省略。
orderAndDrink {
print("厚奶蓋和寒天蒟蒻")
}
有單一參數、無回傳值 closure 當作參數
func orderAndDrink(upgrade: (String) -> Void) {
print("今晚我想來點:")
upgrade("蘋果紅茶")
}
orderAndDrink { (name: String) -> Void in
print("\(name)加厚奶蓋和寒天蒟蒻")
}/*
今晚我想來點:
蘋果紅茶加厚奶蓋和寒天蒟蒻
*/
有單一參數、有回傳值 closure 當作參數
func orderAndDrink(upgrade: (String) -> String) {
print("今晚我想來點:")
let message = upgrade("蘋果紅茶")
print(message)
}orderAndDrink {(name: String) -> String in
return "\(name)加厚奶蓋和寒天蒟蒻"
}/*
今晚我想來點:
蘋果紅茶加厚奶蓋和寒天蒟蒻
*/
・Swift 知道參數型別是 String,可省略。
orderAndDrink { name -> String in
return "\(name)加厚奶蓋和寒天蒟蒻"
}
・Swift 知道回傳值是 String,可省略。
orderAndDrink { name in
return "\(name)加厚奶蓋和寒天蒟蒻"
}
・只有一行,可省略 return。
orderAndDrink { name in
"\(name)加厚奶蓋和寒天蒟蒻"
}
・最後,省略 name in,name 改用 Shorthand parameter names($0, $1 …)。
orderAndDrink {
"\($0)加厚奶蓋和寒天蒟蒻"
}
有多參數、有回傳值 closure 當作參數
func orderAndDrink(upgrade: (String, String) -> String) {
print("今晚我想來點:")
let message = upgrade("蘋果紅茶","正常微冰")
print(message)
}orderAndDrink {
"\($0)加厚奶蓋和寒天蒟蒻,\($1)"
}/*
今晚我想來點:
蘋果紅茶加厚奶蓋和寒天蒟蒻,正常微冰
*/
function 回傳 Closure
// orderAndDrink() 回傳有一個 String 型別參數的 closure,該 closure 無回傳值func orderAndDrink() -> (String) -> Void {
print("今晚我想來點:")
return {
print("\($0)加厚奶蓋和寒天蒟蒻")
}
}// 法一
let message = orderAndDrink()
message("蘋果紅茶")// 法二(也可以但不推薦)
let message2: Void = orderAndDrink()("蘋果紅茶")/*
今晚我想來點:
蘋果紅茶加厚奶蓋和寒天蒟蒻,正常微冰
*/
Closure capturing
func add(adjective: String) -> (String) -> String {
var superString = "超級"
return {
let message = superString + adjective + $0
superString += "超級"
return message
}
}let goodMessage = add(adjective: "可愛的")
print(goodMessage("資穎"))
print(goodMessage("資穎"))let badMessage = add(adjective: "可惡的")
print(badMessage("酸民"))
print(badMessage("酸民"))/*
超級可愛的資穎
超級超級可愛的資穎
超級可惡的酸民
超級超級可惡的酸民
*/