面的例子定义了一个名为count函数,用来计算字符串中基于标准美式英语的元音、辅音以及字符的数量:
- 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)
- }
您可以使用此计数函数来对任意字符串进行字符计数,以检索一个包含三个指定Int值的元素统计总数:
- 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
- }
然而,这些参数名的仅能在函数本身的主体内使用,不能在调用函数时使用。这种形参类型名称被称之为本地形参名(local parameter name),因为它们只能在函数的主体中使用。
?
外部形参名
有时当你调用一个函数将每个形参进行命名是非常有用的,以表明你把每个实参传递给函数的目的。
?
如果你希望使用你函数的人在调用函数时提供形参名称,那除了本地形参名外,你还要为每个形参定义一个外部形参名称。你写一个外部形参名称在它所支持的本地形参名称之前,之间用一个空格来分隔:
- func someFunction(externalParameterName localParameterName: Int) {
- // function body goes here, and can use localParameterName
- // to refer to the argument value for that parameter
- }
| 提示:如果您为形参提供一个外部形参名称,那么外部形参名必须在调用时使用。 |
举一个例子,考虑下面的函数,通过在它们之间插入第三个joiner字符串来连接两个字符串:
- func join(s1: String, s2: String, joiner: String) -> String {
- return s1 + joiner + s2
- }
?
当你调用这个函数,你传递给函数的三个字符串的目的就不是很清楚了:
- join(hello, world, , )
- // returns hello, world
?
为了使这些字符串值的目的更为清晰,为每个join函数形参定义外部形参名称:
- func join(string s1: String, toString s2: String, withJoiner joiner: String)
- -> String {
- return s1 + joiner + s2
- }
在这个版本的join函数中,第一个形参的外部名称string,本地名称s1;第二个形参的外部名称toString,本地名称s2;第三个形参的外部名称是withJoiner,本地名称为joiner。
?
现在,您可以使用这些外部形参名称清楚明确地调用该函数:
- join(string: hello, toString: world, withJoiner: , )
- // returns hello, world
使用外部参数名称使join函数的第二个版本功能以更富有表现力,用户习惯的sentence-like方式调用函数,同时还提供了一个可读的、意图明确的函数体。
| 注意:在别人第一次阅读你的代码不知道你函数形参目的时候,就要考虑到使用外部形参名称了。在调用函数的时候,如果每个形参的目的清晰明确的话,那你就无需指定外部形参名。 |
?
外部参数名称速记
如果你想为一个函数提供一个外部形参名,然而本地形参名已经使用了一个合适的名称了,那你就不需要两次书写该形参的名称。相反,你可以写一次名字,并用一个hash符号(#)作为名称的前缀。这就告诉Swift使用名称相同的本地行参名称和外部形参名称。
?
这个例子定义了一个名为containsCharacter的函数,通过在本地形参名前添加hash符号(#)来定义外部形参名称。
- 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
?
默认形参值
你可以为任何形参定义默认值以作为函数定义的一部分。如果已经定义了默认值,那么调用函数时就可以省略该行参。
| 注意:请在函数形参列表的末尾放置带默认值的形参。这将确保所有函数调用都使用顺序相同的无默认值实参,并让在每种情况下清晰地调用相同的函数。 |
这里有一个早期的join函数,并为参数joiner设置了默认值:
- func join(string s1: String, toString s2: String,
- withJoiner joiner: String = ) -> String {
- return s1 + joiner + s2
- }
?
如果在join函数调用时为joiner提供了字符串值,那么该字符串值可以用来连接两个字符串,就跟以前一样:
- join(string: hello, toString: world, withJoiner: -)
- // returns hello-world
?
但是,如果函数调用时没有为joiner提供值,就会使用单个空格( )的默认值:
- join(string: hello, toString: world)
- // returns hello world
?
有默认值的外部形参名
在大多数情况下,为所有形参提供一个带默认值的外部名是非常有用的(因此要求)。如果在调用函数的时候提供了一个