5 函数(Functions)
函数是用来完成特定任务的独立的代码块。
5.1 定义与调用Defining and Calling Functions
函数名(参数列表)->返回值 {
函数体(要干什么)
}
函数名用来描述其要完成的任务,调用函数时要向函数传递其要求的输入参数,参数顺序必须与函数参数列表一致。
func greet(person: String) -> String {
let greeting = "Hello, " + person + "!"
return greeting
}
print(greet(person: "Anna")) // 3.0带标签
// Prints "Hello, Anna!"
print(greet(person: "Brian"))
// Prints "Hello, Brian!"
func greetAgain(person: String) -> String {
return "Hello again, " + personName + "!"
}
print(greetAgain("Anna"))
5.2 函数参数与返回值Function Parameters and Return Values
无参数函数Functions Without Parameters
func sayHelloWorld() -> String { //虽然没有参数,但括号不能少
return "hello, world"
}
print(sayHelloWorld())
// Prints "hello, world"
多参数函数Functions With Multiple Parameters
func greet(person: String , alreadyGreeted: Bool ) -> String {
//多个参数用逗号分开
if alreadyGreeted {
return greetAgain(person)
} else {
return greet(person)
}
}
print(sayHello("Tim", alreadyGreeted: true))
// Prints "Hello again, Tim!"
无返回值函数Functions Without Return Values
func sayGoodbye(personName: String ) {
print("Goodbye, \(personName)!")
}
sayGoodbye("Dave")
// Prints "Goodbye, Dave!"
函数的返回值在调用时也可以忽略不用:
func printAndCount(stringToPrint: String ) -> Int {
print(stringToPrint)
return stringToPrint.characters.count
}
func printWithoutCounting(stringToPrint: String ) {
printAndCount(stringToPrint)
}
printAndCount("hello, world")
// prints "hello, world" and returns a value of 12
printWithoutCounting("hello, world")
// prints "hello, world" but does not return a value
多返回值函数Functions with Multiple Return Values
可以使用元组(tuple type)作为返回类型用于返回多个值。
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)
}
可以使用dot syntax的访问函数定义中返回值的min and max
let bounds = minMax([8, -6, 2, 109, 3, 71])
print("min is \(bounds.min) and max is \(bounds.max)")
// Prints "min is -6 and max is 109"
函数体中返回值的 tuple’s members不必命名,因为在定义中已命名。
可选元组返回类型Optional Tuple Return Types
如果返回元组类型有可能为空,则使用可空元组optional tuple 如(Int, Int)? or (String, Int, Bool)?.
func minMax(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 = minMax([8, -6, 2, 109, 3, 71]) {
print("min is \(bounds.min) and max is \(bounds.max)")
}
// Prints "min is -6 and max is 109"
重载Overloading
func say() -> String {
return "one"
}
func say() -> Int {
return 1
}
But now you can’t call say like this:
let result = say() // compile error
The call is ambiguous. The call must be used in a context where the expected return type is clear.
let result = say() + "two"
5.3函数参数标签和参数名Function Argument Labels and Parameter Names
每个参数都有标签和参数名,标签在调用函数时放在参数前,增加代码可读性,参数名用于函数体。一般情况下,参数使用参数名作为标签。参数名必须是独一无二的。尽管多个参数可以有相同的参数标签,但不同的参数标签能让你的代码更有可读性。
【参数标签使得参数的作用更明确,并用于区分不同的函数(名称和签名都相同但参数标签不同),更重要的是与Cocoa保持一致】
func someFunction(firstParameterName: Int, secondParameterName: Int) {
// In the function body, firstParameterName and secondParameterName
// refer to the argument values for the first and second parameters.
}
someFunction(firstParameterName: 1, secondParameterName: 2)
Func repeatString(s:String, times:Int) -> String {
var result = ""
for _ in 1…times { result += s }
return result
}
let s = repeatString("hi", times:3)
指定参数标签Specifying Argument Labels
func someFunction(argumentLabel parameterName: Int) {
// In the function body, parameterName refers to the argument value
// for that parameter.
}//如果指定了标签,调用时必须带标签
func greet(person: String, from hometown: String) -> String {
return "Hello \(person)! Glad you could visit from \(hometown)."
}
print(greet(person: "Bill", from: "Cupertino"))
// Prints "Hello Bill! Glad you could visit from Cupertino."
func sayHello(to person: String , and anotherPerson: String ) -> String {
return "Hello \(person) and \(anotherPerson)!"
}
print(sayHello(to: "Bill", and: "Ted"))
// Prints "Hello Bill and Ted!"
省略参数标签Omitting Argument Labels
用 underscore (_) 省略参数标签。也可以用下划线省略参数名,这样,该参数在函数体内不能调用。
func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
// function body goes here
// firstParameterName and secondParameterName refer to
// the argument values for the first and second parameters
}
默认参数值Default Parameter Values
可以为参数设置默认值,设置默认值后调用时可以省略该参数。设置默认值的参数放在列表最后。
func someFunction(parameterWithDefault: Int = 12) {
// function body goes here
// if no arguments are passed to the function call,
// value of parameterWithDefault is 12
}
someFunction(6) // parameterWithDefault is 6
someFunction() // parameterWithDefault is 12
可变参数Variadic Parameters
接受零个或多个指定类型的参数.函数只能有一个可变参数。
func arithmeticMean(numbers: Double ...) -> Double {
var total: Double = 0
for number in numbers {
total += number
}
return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)
// returns 3.0, which is the arithmetic mean of these five numbers
arithmeticMean(3, 8.25, 18.75)
// returns 10.0, which is the arithmetic mean of these three numbers
输入输出参数In-Out Parameters
函数参数默认是常量。试图在函数体内改变这些参数的值将出现编译错误。这可以防止对调用参数的误修改。如果想要函数能修改传递来的参数的值,并在函数调用结束后保持这种修改,将参数作为in-out 参数。
被传递的in-out参数必须是变量,且不能设置默认值,也不能是可变参数,调用时在参数名前加&
。
func swapTwoInts(inout a: Int, inout _ b: Int) {//3.0改为(_ a: inout Int, _ b: inout Int)
let temporaryA = a
a = b
b = temporaryA
}
var a = 5;var b = 20;swapTwoInts(&a,&b);print("a= \(a); b= \(b)")//a=20;b=5
5.4 函数类型Function Types
每个函数都有特定类型,由参数类型和返回类型构成。It is the signature of a function.
func addTwoInts(a: Int, _ b: Int) -> Int {
return a + b
}
func multiplyTwoInts(a: Int, _ b: Int) -> Int {
return a * b
}
这两个函数的类型(Int, Int) -> Int.
funcprintHelloWorld() {
print("hello, world")
}
该函数的类型() -> Void, (() -> (),Void -> Void)
使用函数类型Using Function Types
函数可以赋值给一个变量、作为函数参数或函数返回值。
函数类型作为参数类型Function Types as Parameter Types
func printMathResult(mathFunction: (Int, Int) -> Int , _ a: Int, _ b: Int) {
print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// Prints "Result: 8"
func doThis(f:()->()) { f() }
func whatToDo() { print("I did it") }
doThis(whatToDo)// Prints " I did it "
func countDownFrom(ix:Int) {
print(ix)
if ix > 0 { // stopper
countDownFrom(ix-1)//recurse!
}
}
countDownFrom(10)
函数类型作为返回类型Function Types as Return Types
func stepForward(input: Int) -> Int {
return input + 1
}
func stepBackward(input: Int) -> Int {
return input - 1
}
func chooseStepFunction(backwards: Bool ) -> (Int) -> Int {
return backwards ? stepBackward : stepForward
}
var currentValue = 3
let moveNearerToZero = chooseStepFunction(currentValue > 0)
// moveNearerToZero now refers to the stepBackward() function
print("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
print("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
print("zero!") // 3... // 2... // 1... // zero!
5.5 嵌套函数Nested Functions
可以在函数体内定义函数,称为嵌套函数nested functions.
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(currentValue > 0)
// moveNearerToZero now refers to the nested stepForward() function
while currentValue != 0 {
print("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
print("zero!") // -4... // -3... // -2... // -1... // zero!