# 函数

## 1. 函数定义

```swift

func greet(person: String) -> String {
    let greeting = "Hello, " + person + "!"
    return greeting
}


```

`Swift` 函数定义 使用关键字`func`，后接函数名，参数列表，以及尾置返回值类型。

返回值类型为`Void`时，可省略返回值

## 2. 函数参数标签和参数名字

每个函数参数都有一个`参数标签（argument label）`以及一个`参数名称（parameter name）`。`参数标签`在调用函数的时候使用；调用的时候需要将函数的参数标签写在对应的参数前面。`参数名称`在函数的实现中使用。

默认情况下，函数参数使用参数名称来作为它们的参数标签。

```swift
// firstParameterName 既是参数名，也是参数标签
func someFunction(firstParameterName: Int, secondParameterName: Int) {
    // 在函数体内，firstParameterName 和 secondParameterName 代表参数中的第一个和第二个参数值
}

// 调用时 参数标签：参数
someFunction(firstParameterName: 1, secondParameterName: 2)

```

### 2.1 指定参数标签

可以在参数名称前指定它的参数标签，中间以空格分隔：

```swift

// from 为参数标签 hometown 为参数名
func greet(person: String, from hometown: String) -> String {
    return "Hello \(person)!  Glad you could visit from \(hometown)."
}
print(greet(person: "Bill", from: "Cupertino"))
// 打印“Hello Bill!  Glad you could visit from Cupertino.”

```

### 2.2 忽略参数标签

如果你不希望为某个参数添加一个标签，可以使用一个下划线（\_）来代替一个明确的参数标签。

```swift
// firstParameterName 忽略参数标签
func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
     // 在函数体内，firstParameterName 和 secondParameterName 代表参数中的第一个和第二个参数值
}

// 调用时firstParameterName 不用带参数标签
someFunction(1, secondParameterName: 2)
```

## 3. 默认参数

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

不同于C++，由于参数标签的存在，不需要将没有默认行参的参数放在前面

```swift

// parameterWithDefault 设置默认参数 12
func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
    // 如果你在调用时候不传第二个参数，parameterWithDefault 会值为 12 传入到函数体中。
}
someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault = 6
someFunction(parameterWithoutDefault: 4) // parameterWithDefault = 12
```

## 4. 可变参数

一个`可变参数（variadic parameter）`可以接受零个或多个值。函数调用时，你可以用可变参数来指定函数参数可以被传入不确定数量的输入值。通过在变量类型名后面加入（...）的方式来定义可变参数。

**可变参数的传入值在函数体中变为此类型的一个数组。**

例如，一个叫做 numbers 的 Double... 型可变参数，在函数体内可以当做一个叫 numbers 的 \[Double] 型的数组常量。

```swift
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)
```

感觉类似于C++的`initializer_list`,需要可变参数类型一致，在使用时作为数组使用

## 5. 输入输出参数

**函数参数默认是常量**。试图在函数体中更改参数值将会导致编译错误。这意味着你不能错误地更改参数值。如果你想要一个函数可以修改参数的值，并且想要在这些修改在函数调用结束后仍然存在，那么就应该把这个参数定义为**输入输出参数**（In-Out Parameters）。

定义一个输入输出参数时，在参数定义前加 `inout` 关键字。

你只能传递变量给输入输出参数。你不能传入常量或者字面量，因为这些量是不能被修改的。当传入的参数作为输入输出参数时，需要在参数名前加 `&` 符，表示这个值可以被函数修改。

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

```swift
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)

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

```

> inout 参数 可以理解为 C/C++ 中参数的引用传递，能够修改参数引用的值。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gitbook.existorlive.cn/kai-fa-yu-yan-xue-xi/swift/6.-han-shu/1.-han-shu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
