//: Playground - noun: a place where people can play
import UIKit
// # 定义和调用函数
// 函数同名没有问题,只要形式参数不一样就可以了
// # 函数的形式参数和返回值
// trick: 无返回值函数可以在函数体内调用return来结束函数。实际上是返回了Void,一个没有元素的元组()
// trick: 用_接收无用返回值
func printAndCount(string: String) -> Int {
print(string)
return string.count
}
func printWithoutCounting(string: String) {
let _ = printAndCount(string: string) // or we can omit 'let _'
}
printWithoutCounting(string: "hello, world")
// 返回元组的函数
// trick: 以下找min、max的方法很重要***
func minMax(array: [Int]) -> (min: Int, max: Int) {
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..<array.count] {
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
}
let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) // bounds's type is (min: Int, max: Int)
print("min is \(bounds.min) and max is \(bounds.max)")
// 增加函数的健壮性,选用返回可选元组的函数
func betterMinMax(array: [Int]) -> (min: Int, max: Int)? {
if array.isEmpty { return nil }
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..<array.count] {
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
}
if let bounds = betterMinMax(array: [8, -6, 2, 109, 3, 71]) {
print("min is \(bounds.min) and max is \(bounds.max)")
}
// trick: 函数返回可选项
func someFuncThatReturnsAnOptional() -> Int? {
// do not need to return an optional inside the func
return 0
// also OK:
// var a: Int? = 0
// return a
}
var a = someFuncThatReturnsAnOptional()
// # 函数实际参数标签和形式参数名
// 实际参数标签能提高代码易读性,默认情况下与形式参数相同,可以用_省略
func greet(person: String, from hometown: String) -> String {
return "Hello, \(person) from \(hometown)!"
}
greet(person: "Bill", from: "America")
// 默认形式参数值,print(_:separator:terminator:)就有默认值" "and"\n",所以可以调用前者加后两者的子集
// 要求:在定义func时,把不带有默认值的形式参数放到函数的形式参数列表中带有默认值的形式参数前边
func someFunc(parameter: Int = 12) {
}
someFunc()
someFunc(parameter: 6)
// 可变形式参数,在传入后参数会被当成该类型的数组处理.一个函数最多只有一个可变形式参数
func arithmeticMean(numbers: Double...) -> Double {
var total: Double = 0
for number in numbers {
total += number
}
return total / Double(numbers.count)
}
arithmeticMean(numbers: 1, 2, 3)
// 输入输出形式参数,把变量作为实际参数.好处:能够改变参数的值,还能将改变后的值保留到函数外.
// 如果以输入输出形式参数传一个拥有观察者的变量给函数, willSet 和 didSet 观察者一定会被调用,就算实际上并没有改变其值。这是由于输入输出形式参数的拷贝入拷贝出存储模型导致的:值一定会在函数结束后写回变量。***
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt) // 用&来明确该变量可以被函数修改
someInt
anotherInt
// # 函数类型
// 例如:(Int, Int) -> Int, () -> Void
func addTwoInts(what a: Int, theFuck b: Int) -> Int {
return a + b
}
func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
return a * b
}
// 把函数作为变量,注意只用了函数名,没有参数.而且发现重要一点:传递过后使用新变量,直接无视原来函数的实际参数标签,这样要简单多了.注意,是引用传递.***
var mathFunction: (Int, Int) -> Int = addTwoInts
mathFunction(1, 1)
mathFunction = multiplyTwoInts
mathFunction(1, 1)
let anotherMathFunction = addTwoInts // 类型推断
// trick: 函数类型作为形式参数类型.引用传递.***
func printMathResult(withMethod mathFunction: (Int, Int) -> Int, of a: Int, and b: Int) {
// 隐式执行了 let (mathFunction: (Int, Int) -> Int, a: Int, b: Int) = (addTwoInts, 3, 5)
print("Result: \(mathFunction(a, b))")
}
printMathResult(withMethod: addTwoInts, of: 3, and: 5)
// trick: 函数作为返回值.引用传递.
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
// 内嵌函数,在外部是被隐藏起来的,可以通过返回内部的内嵌函数来在另外的范围使用
func stepForward(_ input: Int) -> Int {
return input + 1
}
func stepBackward(_ input: Int) -> Int {
return input - 1
}
return backwards ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(backwards: currentValue > 0) // moveNearerToZero指向了stepForward or stepBackward指向的函数
currentValue = moveNearerToZero(currentValue)
currentValue = moveNearerToZero(currentValue)
// # 内嵌函数
// 如上所述
// 函数不能捕获值,除非是定义为全局变量
func main() -> Int {
let freezeInC = 0.0
let freezeInF = fahrenheit(FromCelsiusOf: freezeInC)
return 0
}
func fahrenheit(FromCelsiusOf cel: Double) -> Double {
// print(freezeInC) WRONG!
return cel * 1.8 + 32.0
}
main()
网友评论