greet(person:)
,之所以叫这个名字,是因为这个函数用一个人的名字当做输入,并返回向这个人问候的语句。为了完成这个任务,你需要定义一个输入参数——一个叫做 person
的 String
值,和一个包含给这个人问候语的 String
类型的返回值:func
作为前缀。指定函数返回类型时,用返回箭头 ->
(一个连字符后跟一个右尖括号)后跟返回类型的名称的方式来表示。greet(person:)
函数时,在圆括号中传给它一个 String
类型的实参,例如 greet(person: "Anna")
。正如上面所示,因为这个函数返回一个 String
类型的值,所以 greet
可以被包含在 print(_:separator:terminator:)
的调用中,用来输出这个函数的返回值。注意print(_:separator:terminator:)
函数的第一个参数并没有设置一个标签,而其他的参数因为已经有了默认值,因此是可选的。关于这些函数语法上的变化详见下方关于 函数参数标签和参数名以及默认参数值。
greet(person:)
的函数体中,先定义了一个新的名为 greeting
的 String
常量,同时,把对 personName
的问候消息赋值给了 greeting
。然后用 return
关键字把这个问候返回出去。一旦 return greeting
被调用,该函数结束它的执行并返回 greeting
的当前值。greet(person:)
。上面的例子展示的是用 "Anna"
和 "Brian"
调用的结果,该函数分别返回了不同的结果。String
消息:String
参数值和一个标识为 alreadyGreeted
的 Bool
值,来调用 greet(person:alreadyGreeted:)
函数。注意这个函数和上面 greet(person:)
是不同的。虽然它们都有着同样的名字 greet
,但是 greet(person:alreadyGreeted:)
函数需要两个参数,而 greet(person:)
只需要一个参数。greet(person:)
函数的另一个版本,这个函数直接打印一个 String
值,而不是返回它:注意严格地说,即使没有明确定义返回值,该greet(Person:)
函数仍然返回一个值。没有明确定义返回类型的函数的返回一个Void
类型特殊值,该值为一个空元组,写成 ()。
printAndCount(string:)
,输出一个字符串并返回 Int
类型的字符数。第二个函数 printWithoutCounting(string:)
调用了第一个函数,但是忽略了它的返回值。当第二个函数被调用时,消息依然会由第一个函数输出,但是返回值不会被用到。注意返回值可以被忽略,但定义了有返回值的函数必须返回一个值,如果在函数定义底部没有返回任何值,将导致编译时错误。
minMax(array:)
的函数,作用是在一个 Int
类型的数组中找出最小值与最大值。minMax(array:)
函数返回一个包含两个 Int
值的元组,这些值被标记为 min
和 max
,以便查询函数的返回值时可以通过名字访问它们。minMax(array:)
的函数体中,在开始的时候设置两个工作变量 currentMin
和 currentMax
的值为数组中的第一个数。然后函数会遍历数组中剩余的值并检查该值是否比 currentMin
和 currentMax
更小或更大。最后数组中的最小值与最大值作为一个包含两个 Int
值的元组返回。.
语法来检索找到的最小值与最大值:nil
的事实。你可以通过在元组类型的右括号后放置一个问号来定义一个可选元组,例如 (Int, Int)?
或 (String, Int, Bool)?
注意可选元组类型如(Int, Int)?
与元组包含可选类型如(Int?, Int?)
是不同的。可选的元组类型,整个元组是可选的,而不只是元组中的每个元素值。
minMax(array:)
函数返回了一个包含两个 Int
值的元组。但是函数不会对传入的数组执行任何安全检查,如果 array
参数是一个空数组,如上定义的 minMax(array:)
在试图访问 array[0]
时会触发一个运行时错误。minMax(array:)
函数改写为使用可选元组返回类型,并且当数组为空时返回 nil
:minMax(array:)
函数返回的是一个存在的元组值还是 nil
:greeting(for:)
函数的完整定义是打招呼内容的返回,这就意味着它能使用隐式返回这样更简短的形式。anothergreeting(for:)
函数返回同样的内容,却因为 return
关键字显得函数更长。任何一个可以被写成一行 return
语句的函数都可以忽略 return
。greet(person:)
函数,接收一个人的名字和他的家乡,并且返回一句问候:_
)来代替一个明确的参数标签。...
)的方式来定义可变参数。numbers
的 Double...
型可变参数,在函数体内可以当做一个叫 numbers
的 [Double]
型的数组常量。inout
关键字。一个 输入输出参数
有传入函数的值,这个值被函数修改,然后被传出函数,替换原来的值。想获取更多的关于输入输出参数的细节和相关的编译器优化,请查看 输入输出参数 一节。&
符,表示这个值可以被函数修改。注意输入输出参数不能有默认值,而且可变参数不能用inout
标记。
swapTwoInts(_:_:)
函数有两个分别叫做 a
和 b
的输入输出参数:swapTwoInts(_:_:)
函数简单地交换 a
与 b
的值。该函数先将 a
的值存到一个临时常量 temporaryA
中,然后将 b
的值赋给 a
,最后将 temporaryA
赋值给 b
。Int
型的变量来调用 swapTwoInts(_:_:)
。需要注意的是,someInt
和 anotherInt
在传入 swapTwoInts(_:_:)
函数前,都加了 &
的前缀:someInt
和 anotherInt
的原始值在 swapTwoInts(_:_:)
函数中被修改,尽管它们的定义在函数体外。注意输入输出参数和返回值是不一样的。上面的swapTwoInts
函数并没有定义任何返回值,但仍然修改了someInt
和anotherInt
的值。输入输出参数是函数对函数体外产生影响的另一种方式。
addTwoInts
和 multiplyTwoInts
。这两个函数都接受两个 Int
值, 返回一个 Int
值。(Int, Int) -> Int
,可以解读为:Int
型的参数并返回一个 Int
型的值”。() -> Void
,或者叫“没有参数,并返回 Void
类型的函数”。mathFunction
的变量,类型是‘一个有两个 Int
型的参数并返回一个 Int
型的值的函数’,并让这个新变量指向 addTwoInts
函数”。addTwoInts
和 mathFunction
有同样的类型,所以这个赋值过程在 Swift 类型检查(type-check)中是允许的。mathFunction
来调用被赋值的函数了:(Int, Int) -> Int
这样的函数类型作为另一个函数的参数类型。这样你可以将函数的一部分实现留给函数的调用者来提供。printMathResult(_:_:_:)
函数,它有三个参数:第一个参数叫 mathFunction
,类型是 (Int, Int) -> Int
,你可以传入任何这种类型的函数;第二个和第三个参数叫 a
和 b
,它们的类型都是 Int
,这两个值作为已给出的函数的输入值。printMathResult(_:_:_:)
被调用时,它被传入 addTwoInts
函数和整数 3
和 5
。它用传入 3
和 5
调用 addTwoInts
,并输出结果:8
。printMathResult(_:_:_:)
函数的作用就是输出另一个适当类型的数学函数的调用结果。它不关心传入函数是如何实现的,只关心传入的函数是不是一个正确的类型。这使得 printMathResult(_:_:_:)
能以一种类型安全(type-safe)的方式将一部分功能转给调用者实现。stepForward(_:)
和 stepBackward(_:)
。stepForward(_:)
函数返回一个比输入值大 1
的值。stepBackward(_:)
函数返回一个比输入值小 1
的值。这两个函数的类型都是 (Int) -> Int
:chooseStepFunction(backward:)
的函数,它的返回类型是 (Int) -> Int
类型的函数。chooseStepFunction(backward:)
根据布尔值 backwards
来返回 stepForward(_:)
函数或 stepBackward(_:)
函数:chooseStepFunction(backward:)
来获得两个函数其中的一个:currentValue
逐渐接近到0是需要向正数走还是向负数走。currentValue
的初始值是 3
,这意味着 currentValue > 0
为真(true),这将使得 chooseStepFunction(_:)
返回 stepBackward(_:)
函数。一个指向返回的函数的引用保存在了 moveNearerToZero
常量中。moveNearerToZero
指向了正确的函数,它可以被用来数到零:chooseStepFunction(backward:)
函数: