五、函数 Functions
1. 函数
1.1 多返回值函数——使用元祖类型(tuple)作为函数的返回值
func count(string: String) -> (vowels: Int, consonants: Int, others: Int) { var vowels = 0, consonants = 0, others = 0 for character in string { switch String(character).lowercaseString { case "a", "e", "i", "o", "u": ++vowels case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z": ++consonants default: ++others } return (vowels, consonants, others)
}
let total = count("some arbitrary string!") println("\(total.vowels) vowels and \(total.consonants) consonants") // prints "6 vowels and 13 consonants"
1.2 函数的外部参数名 External Parameter Names
外部参数名用于给参数取别名,可以起到提示的作用。
定义方法:
func someFunction(externalParameterName localParameterName: Int) {
}
不使用外部参数名:
func join(s1: String, s2: String, joiner: String) -> String { return s1 + joiner + s2 } join("hello", "world", ", ")
使用外部参数名:
func join(fromString s1: String, toString s2: String, withJoiner joiner: String)-> String { return s1 + joiner + s2 } join(fromString: "hello", toString: "world", withJoiner: ", ")
1.3 速记外部参数名 Shorthand External Parameter Names
当localParameterName与externalParameterName 相同时,可以使用“#”(hash symbol)代替外部参数名
func join(#s1: String, #s2: String, #joiner: String)-> String { return s1 + joiner + s2 } join(s1: "hello", s2: "world", joiner: ", ")
1.4 参数的默认值——默认值参数 Default Parameter Values
在定义函数的时候,可以给函数的参数设置一个默认值。当参数有默认值时,调用这个函数时可以可以忽略这个参数。一般情况下,请将有默认值的参数放在函数参数表的最后位置。
func join(fromString s1: String, toString s2: String, withJoiner joiner: String = “”) -> String{ return s1 + joiner + s2 } join(fromString: "hello", toString: "world", withJoiner: ", ") //hello,world join(fromString: "hello", toString: "world") // "hello world"
1.5 默认值参数的外部变量名
当函数有默认值参数时,如果没有提供默认值参数的外部参数名,调用时,默认值参数会被编译器自动加上外部参数名(automatic external name),这个外部参数名实际上是“#”,即与内部参数名同名。
func join(s1: String, s2: String, joiner: String = "") -> String { return s1 + joiner + s2 } join("hello", "world", joiner: "-") // "hello-world"
1.6 不定参数函数 Variadic Parameters
在参数后加上三个点(...)表示这个参数是可变参数,传递给可变参数的值由一组类似的值组成。
一个函数只能有一个可变参数,并且可变参数要出现在参数表的最后位置。如果一个函数既有默认参数值,又有可变参数,可变参数依然要放到参数表的最后位置。
//计算算术平均值 func arithmeticMean(numbers: Double...) -> Double { var total: Double = 0 for number in numbers { total += number } return total / Double(numbers.count) } rithmeticMean(1, 2, 3, 4, 5) // returns 3.0, which is the arithmetic mean of these five numbers arithmeticMean(3, 8, 19) // returns 10.0, which is the arithmetic mean of these three numbers
1.7 可变参数和不可变参数 Constant and Variable Parameters
函数的参数默认是constant,尝试在函数体中修改不可变参数的值将导致编译时错误。
可变参数相当于给参数的值创建了一个可修改的副本(a new modifiable copy)。定义可变参数的方法是在参数名钱加上var关键字。
func alignRight(var string: String, count: Int, pad: Character) -> String { let amountToPad = count - countElements(string) for _ in 1...amountToPad { string = pad + string } return string } let originalString = "hello" let paddedString = alignRight(originalString, 10, "-") // paddedString is equal to "-----hello" // originalString is still equal to "hello"
1.8 In-Out 参数
C语言中,如果某个函数的作用是交换两个参数的值,那么应该传入这两个参数的指针。类似的,swift中,这两个参数要用inout关键字表示,函数外使用时,要加上&符号。例子如下:
func swapTwoInts1(var a: Int, var b: Int){ let temp = a; a = b; b = temp; } func swapTwoInts2(inout a: Int, inout b: Int){ let temp = a; a = b; b = temp; } var a = 10; var b = 20; swapTwoInts1(a, b) println("a:\(a), b:\(b)")//a:10, b:20 swapTwoInts2(&a, &b) println("a:\(a), b:\(b)")//a:20, b:10
1.9 函数类型 Function Types
每个函数都有类型,即函数类型(function type),它由参数类型和返回值类型复合而成。
例如:
func addTwoInts(a: Int, b: Int) -> Int { return a + b } func multiplyTwoInts(a: Int, b: Int) -> Int { return a * b }
上面两个函数的类型都是 (Int, Int) -> Int
func printHelloWorld() { println("hello, world") }
上面函数的类型是 () -> ()
1.10 函数类型的使用 Using Function Types
在swift中,函数类型的使用与其他类型一样。例如:
var mathFunction: (Int, Int) -> Int = addTwoInts println("Result: \(mathFunction(2, 3))") //prints "Result: 5"
上面的代码定义了一个名为 mathFunction 的变量,他是一个 (Int, Int) -> Int 的函数类型,他的值为 addTwoInts 函数的引用。
函数 multiplyTwoInts 与 addTwoInts 具有相同的函数类型,相同类型的不同函数可以赋值给同一个变量,所以可以进行如下赋值:
mathFunction = mutiplyTwoInts println(("Result: \(mathFunction(2, 3))") // prints "Result: 6"
你也可以定义函数类型为常量:
let anotherMathFunction = addTwoInts
1.11 函数类型参数 Function Types as Parameter Types
你可以将函数类型如 (Int, Int) -> Int 的参数作为另一个函数的参数来使用,例如:
func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int){ println("\(mathFunction(a, b))") } printMathResult(addTwoInts, 3, 5) // prints "Result: 8"
当执行语句 printMathResult(addTwoInts, 3, 5) 时,编译器将函数 addTwoInts 、3 和 5 传入 printMathResult 中,然后调用 addTwoInts 函数,得到结果8,最后打印出来。
1.12 函数类型返回值 Function Types as Return Type
你可以将函数类型作为函数的参数类型来使用,如:
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)
1.13 嵌套函数 Nested Function
我们在上面所有看到的例子中的函数都是全局函数(global functions),你也可以在函数体内再定义函数,这就是嵌套函数(或许叫子函数比较形象)。
嵌套函数默认对外部不可见,只能在包含它的函数中使用(be called and used by their enclosing function)(或者叫母函数比较形象)。一个母函数可以返回它的一个子函数,这样子函数就能在其他函数中使用了。
例如:利用嵌套函数重写上面的 chooseStepFunction 函数
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 = 3
let moveNearerToZero = chooseStepFunction(currentValue > 0)