Swift学习笔记 (十五) 函数(下)

忽略参数标签

如果你不希望为某个参数添加一个标签,可以使⽤一个下划线( _ )来代替⼀个明确的参数标签。

func someFunction(_ firstParameterName: Int, secondParameterName: Int) {

// 在函数体内,firstParameterName 和 secondParameterName 代表参数中的第一个和第二个参数值

}

someFunction(1, secondParameterName: 2)

如果⼀个参数有一个标签,那么在调用的时候必须使用标签来标记这个参数。

 

默认参数值

你可以在函数体中通过给参数赋值来为任意一个参数定义默认值(Deafult Value)。当默认值被定义后,调⽤这个函数时可以忽略

这个参数。

func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {

            // 如果你在调用时候不传第二个参数,parameterWithDefault 会值为 12 传入到函数体中。

}

someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6)               // parameterWithDefault = 6

someFunction(parameterWithoutDefault: 4)                                                           // parameterWithDefault = 12

将不带有默认值的参数放在函数参数列表的最前面。一般来说,没有默认值的参数更加的重要,将不带默认值的参数放在最前面

保证在函数调用时,非默认参数的顺序是一致的,同时也使得相同的函数在不同情况下调用时显得更为清晰。

 

可变参数

一个可变参数(variadic parameter)可以接受零个或多个值。函数调用时,你可以用可变参数来指定函数参数可以被传入不确定

数量的输入值。通过在变量类型名后面加入( ... )的方式来定义可变参数。

可变参数的传入值在函数体中变为此类型的一个数组。例如,一个叫做 numbers 的 Double... 型可变参数,在函数体内可以当

做一个叫 numbers 的 [Double] 型的数组常量。

下面的这个函数用来计算一组任意长度数字的算术平均数(arithmetic mean):

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)

// 返回 3.0, 是这 5 个数的平均数。

arithmeticMean(3, 8.25, 18.75)

// 返回 10.0, 是这 3 个数的平均数。

注意

一个函数最多只能拥有⼀个可变参数。

 

输入输出参数

函数参数默认是常量。试图在函数体中更改参数值将会导致编译错误。这意味着你不能错误地更改参数值。如果你想要一个函数

可以修改参数的值,并且想要这些修改在函数调用结束后仍然存在,那么就应该把这个参数定义为输入输出参数 (In-Out

Parameters)。

定义一个输入输出参数时,在参数定义前加 inout 关键字。一个输入输出参数有传入函数的值,这个值被函数修改,然后被传出

函数,替换原来的值。想获取更多的关于输入输出参数的细节和相关的编译器优化,请查看《输⼊入输出参数》一 节。

你只能传递变量给输入输出参数。你不能传入常量或者字⾯量,因为这些值是不能被修改的。当传入的参数作为输入输出参数

时,需要在参数名前加 & 符,表示这个值可以被函数修改。

注意

输入输出参数不能有默认值,而且可变参数不能用 inout 标记。

下例中, swapTwoInts(_:_:) 函数有两个分别叫做 a 和 b 的输入输出参数:

func swapTwoInts(_ a: inout Int, _ b: inout Int) {

       let temporaryA = a

       a=b

       b = temporaryA

}

swapTwoInts(_:_:) 函数简单地交换 a 与 b 的值。该函数先将 a 的值存到一个临时常量 temporaryA 中, 然后将 b 的值赋给 a ,最

后将 temporaryA 赋值给 b 。

你可以用两个 Int 型的变量来调用 swapTwoInts(_:_:) 。需要注意的是, someInt 和 anotherInt 在传入swapTwoInts(_:_:) 函数前,

都加了 & 的前缀:

var someInt = 3

var anotherInt = 107

swapTwoInts(&someInt, &anotherInt)

print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")

// 打印“someInt is now 107, and anotherInt is now 3”

从上⾯这个例子中,我们可以看到 someInt 和 anotherInt 的原始值在 swapTwoInts(_:_:) 函数中被修改,尽管它们的定义在函数

体外。

注意

输⼊输出参数和返回值是不一样的。上面的 swapTwoInts 函数并没有定义任何返回值,但仍然修改了 someInt 和

anotherInt 的值。输入输出参数是函数对函数体外产生影响的另一种方式。

 

函数类型

每个函数都有特定的函数类型,函数的类型由函数的参数类型和返回类型组成。例如:

func addTwoInts(_ a: Int, _ b: Int) -> Int {

         return a + b

}


func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {

          return a * b

}

这个例子中定义了两个简单的数学函数: addTwoInts 和 multiplyTwoInts 。这两个函数都接受两个 Int 值, 返回一个 Int 值。

这两个函数的类型是 (Int, Int) -> Int ,可以解读为: “这个函数类型有两个 Int 型的参数并返回一个 Int 型的值”。 下⾯是另一个例

子,一个没有参数,也没有返回值的函数:

func printHelloWorld() {

        print("hello, world")

}

这个函数的类型是: () -> Void ,或者叫“没有参数,并返回值为 Void 类型的函数”。

 

使用函数类型

在 Swift 中,使用函数类型就像使用其他类型一样。例如,你可以定义一个类型为函数的常量或变量,并将适当的函数赋值给它:

var mathFunction: (Int, Int) -> Int = addTwoInts

这段代码可以被解读为:

”定义一个叫做 mathFunction 的变量,类型是‘一个有两个 Int 型的参数并返回一个 Int 型的值的函数’,并让这个新变量指向 

addTwoInts 函数”。

addTwoInts 和 mathFunction 有同样的类型,所以这个赋值过程在 Swift 类型检查(type-check)中是允许的。 现在,你可以用 

mathFunction 来调用被赋值的函数了:

print("Result: \(mathFunction(2, 3))")

// Prints "Result: 5"

有相同匹配类型的不同函数可以被赋值给同一个变量,就像非函数类型的变量一样:

mathFunction = multiplyTwoInts

print("Result: \(mathFunction(2, 3))")

// Prints "Result: 6"

就像其他类型一样,当赋值一个函数给常量或变量时,你可以让 Swift 来推断其函数类型:

let anotherMathFunction = addTwoInts

// anotherMathFunction 被推断为 (Int, Int) -> Int 类型

 

函数类型作为参数类型

你可以⽤ (Int, Int) -> Int 这样的函数类型作为另一个函数的参数类型。这样你可以将函数的一部分实现留给函数的调用者来提

供。

下⾯是另一个例子,正如上面的函数一样,同样是输出某种数学运算结果:

func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {

       print("Result: \(mathFunction(a, b))")

}

printMathResult(addTwoInts, 3, 5)// 打印“Result: 8”

这个例子定义了 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 :

func stepForward(_ input: Int) -> Int {

          return input + 1

}


func stepBackward(_ input: Int) -> Int {

        return input - 1

}

如下名为 chooseStepFunction(backward:) 的函数,它的返回类型是 (Int) -> Int 类型的函数。 chooseStepFunction(backward:) 

根据布尔值 backwards 来返回 stepForward(_:) 函数或 stepBackward(_:) 函数:

func chooseStepFunction(backward: Bool) -> (Int) -> Int {

        return backward ? stepBackward : stepForward

}

你现在可以用 chooseStepFunction(backward:) 来获得两个函数其中的一个:

var currentValue = 3

let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)

// moveNearerToZero 现在指向 stepBackward() 函数。

上⾯这个例子中计算出从 currentValue 逐渐接近到0是需要向正数走还是向负数走。 currentValue 的初始值是3 ,这意味着 

currentValue > 0 为真(true),这将使得 chooseStepFunction(_:) 返回stepBackward(_:) 函数。一个指向返回的函数的引⽤保存在

了 moveNearerToZero 常量中。

现在, moveNearerToZero 指向了正确的函数,它可以被用来数到零:

print("Counting to zero:")

// Counting to zero:

while currentValue != 0 {

         print("\(currentValue)... ")

         currentValue = moveNearerToZero(currentValue)
}

print("zero!")

// 3...

// 2...

// 1...

// zero!

 

嵌套函数

到目前为止本章中你所见到的所有函数都叫全局函数(global functions),它们定义在全局域中。你也可以把函数定义在别的函数

体中,称作嵌套函数(nested functions)。

默认情况下,嵌套函数是对外界不可见的,但是可以被它们的外围函数(enclosing function)调用。一个外围函数也可以返回它

的某一个嵌套函数,使得这个函数可以在其他域中被使用。

你可以用返回嵌套函数的方式重写 chooseStepFunction(backward:) 函数:

func chooseStepFunction(backward: Bool) -> (Int) -> Int {

        func stepForward(input: Int) -> Int { return input + 1 }

        func stepBackward(input: Int) -> Int { return input - 1 }

        return backward ? stepBackward : stepForward

}

var currentValue = -4

let moveNearerToZero = chooseStepFunction(backward: 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!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值