定义与调用
用func作为前缀来标志这是一个函数,用 (->) 加返回类型的名字表示该函数返回什么类型
func sayHelloAgain(personName: String) -> String {
return "Hello again, " + personName + "!"
}
println(sayHelloAgain("Anna"))
// prints "Hello again, Anna!"
参数与返回值
Swift中的函数的参数和返回值可以定义的非常灵活,包括从只带一个未命名的简单函数到复杂的带有表达式参数名和不同参数选项的复合函数.
- 多个参数,写在圆括号中,用逗号分隔
func halfOpenRangeLength(start: Int, end: Int) -> Int {
return end - start
}
println(halfOpenRangeLength(1, 10))
// prints "9"
- 无参,尽管没有参数,圆括号也不能省略,调用的时候也是函数名加圆括号
func sayHelloWorld() -> String {
return "hello, world"
}
println(sayHelloWorld())
// prints "hello, world"
- 无返回值
没有返回值就没有返回箭头和返回类型
func sayGoodbye(personName: String) {
println("Goodbye, \(personName)!")
}
sayGoodbye("Dave")
// prints "Goodbye, Dave!"
- 多返回值
用元组来让多个值作为一个复合值从函数中返回
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"
函数参数名
- 函数的参数名只能在函数体内使用,称为局部参数名
func someFunction(parameterName: Int) {
// function body goes here, and can use parameterName
// to refer to the argument value for that parameter
}
外部参数名
- 如果希望在函数调用的时候使用函数提供的参数的名字,就需要再定义一个外部参数名,写在局部参数名之前,空格分开
func someFunction(externalParameterName localParameterName: Int) {
// function body goes here, and can use localParameterName
// to refer to the argument value for that parameter
}
- 以下是不使用和使用外部参数名的例子,其实代码执行是一样的,但是有了外部参数名,能让人比较直观的了解代码是要干什么的,增加可读性
func join(s1: String, s2: String, joiner: String) -> String {
return s1 + joiner + s2
}
join("hello", "world", ", ")
// returns "hello, world"
func join(string s1: String, toString s2: String, withJoiner joiner: String) -> String {
return s1 + joiner + s2
}
join(string: "hello", toString: "world", withJoiner: ", ")
// returns "hello, world"
简写外部参数名
一个的简写方式,在参数名前加(#),告诉Swfit这个参数既作为外部参数,也作为局部参数
func containsCharacter(#string: String, #characterToFind: Character) -> Bool {
for character in string {
if character == characterToFind {
return true
}
}
return false
}
let containsAVee = containsCharacter(string: "aardvark", characterToFind: "v")
// containsAVee equals true, because "aardvark" contains a "v"
默认参数
在函数定义的时候为每个参数定义默认值,当函数调用的时候可以略去这个参数
func join(string s1: String, toString s2: String,
withJoiner joiner: String = " ") -> String {
return s1 + joiner + s2
}
join(string: "hello", toString: "world", withJoiner: "-")
// returns "hello-world"
join(string: "hello", toString: "world")
// returns "hello world"
默认参数的外部参数名
func join(s1: String, s2: String, joiner: String = " ") -> String {
return s1 + joiner + s2
}
join("hello", "world", joiner: "-")
// returns "hello-world"
可变参数
函数调用时,如果不确定参数的数量,通过在变量类型后面加 (...) 定义可变参数,一个函数最多能有一个可变参数,且必须是函数表中最后的一个,避免函数调用时出现歧义,所以一个函数如果有一个或多个带默认值的参数,还有一个可变参数,千万把可变参数放在最后
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, 19)
// returns 10.0, which is the arithmetic mean of these three numbers
常量参数和变量参数
函数参数默认都是常量,想在函数体内更改参数值将会报错,但有时候,会在函数中有传入参数的变量值副本,通过指定一个或多个参数作为变量参数参数,从而避免在函数中定义新的变量,通过在参数名前加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"
alignRight函数将参数string定义为变量参数,意味着string作为一个局部变量,用传入的字符串值初始化,并在函数体中进行操作,但也仅仅存在于函数调用的生命周期内
输入输出参数
如果想要一个函数可以修改参数的值,并且这些修改在函数结束调用后仍然存在,那就可以定义为输入输出参数,在参数前面添加inout关键字,这个值被函数修改后被传出函数,并替换原来的值,同时,传入的只能是变量而不能是常量,当传入的参数作为作为输入输出参数时,需要在参数面前加 & 符号,表示这个值可以被修改
func swapTwoInts(inout a: Int, inout b: Int) {
let temporaryA = a
a = b
b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
println("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// prints "someInt is now 107, and anotherInt is now 3"
函数类型
每个函数都有特定的函数类型,由参数类型和返回类型组成
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")
}
// 这个函数类型是 () -> ()
使用函数类型
- 使用函数类型就跟使用其他类型一样,比如可以定义一个常量或变量,类型就是函数,而且可以给这个函数赋值
以下定义一个mathFunction的变量,类型是 两个int型参数并返回int型的函数,并让这个变量指向addTwoInts函数
var mathFunction: (Int, Int) -> Int = addTwoInts
println("Result: \(mathFunction(2, 3))")
// prints "Result: 5"
- 有相同参数类型且返回类型相同的不同函数可以赋值给同一个变量
mathFunction = multiplyTwoInts
println("Result: \(mathFunction(2, 3))")
// prints "Result: 6"
- 在赋一个函数给常量或变量时,可以省略函数类型
let anotherMathFunction = addTwoInts
// anotherMathFunction is inferred to be of type (Int, Int) -> Int
函数类型作为参数类型
用 (Int, Int) -> Int 这样的函数类型作为另一个函数的参数,将函数的一部分实现交给函数的调用者
func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int) {
println("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// prints "Result: 8"
函数类型作为返回类型
在返回箭头 (->) 后写一个完整的函数类型,表示将函数类型作为另一个函数的返回类型
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
println("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
println("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
println("zero!")
// 3...
// 2...
// 1...
// zero!
嵌套函数
定义在全局域中的称为全局函数,将函数定义在别的函数中,称为嵌套函数
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 {
println("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
println("zero!")
// -4...
// -3...
// -2...
// -1...
// zero!