# 関数とは

関数とは、特定のタスクを実行するためのコード群です。Swiftの関数には型があり、引数の型と戻り値の型で構成されています。関数の型は他の型と同じように使うことができるので、関数を引数として他の関数に渡したり、関数から関数を返したりすることができます。

# 関数の書き方

Swiftの関数は次のフォーマットで書くことができます。

func 関数名(引数名: 型, 引数名: 型) -> 戻り値の型 {
  実行する処理の記述
}

次の例では、Int型の引数を受け取り、Int型の戻り値を返しています。

func test(_ int: Int) -> Int {
  return int + int
}

test(1) // 2

# 引数

# 外部引数名

Swiftでは、引数に外部引数名をつけることができます。外部引数名とは、引数に名前をつけて呼び出す際に引数の意味が分りやすいようにする仕組みです。

外部引数名は、次のフォーマットで書くことができます。

func 関数名(外部引数名 引数名: 型) -> 戻り値の型 {}

int という内部の引数とは別に、num という外部引数名をつけてみましょう。 呼び出す際は、num: 値 でキーワードを指定してください。

func test(num int: Int) -> Int {
  return int + int
}

test(num: 1) // 2

外部引数名を指定しないと、コンパイラはエラーを出力します。

func test(num int: Int) -> Int {
  return int + int
}

test(1)

// error: missing argument label 'num:' in call
// test(1)
//      ^
//      num: 

# 外部引数名の省略

外部引数名は、省略することができます。

省略する際は、_ を記述してください。

func test(_ int: Int, _ int2: Int) -> Int {
  return int + int
}

test(1, 2) // 3

# デフォルトの引数

引数には、デフォルトの値を指定することができます。

呼び出す際に、引数を渡さなかった場合はそのデフォルト値が使われることになります。

func test(_ int: Int = 10) -> Int {
  return int + int
}

test(1) // 2
test() // 20

# inout

Swiftには ポインタ という概念はありませんが、inout を使うことで、関数の引数に値を渡して、それを関数内で変更することができます。

引数の型の前に、inout を記述し、呼び出す際は、 & を変数につけてください。

func test(int: inout Int) {
  int = int + int
}

var val: Int = 1

test(int: &val)
print(val) // 2

test(int: &val)
print(val) // 4

test(int: &val)
print(val) // 8

上記の例では、呼び出し元の変数 val の値が変更されているのが確認できます。

# 可変長引数

Swiftでは、関数に可変長引数を指定することができます。

可変長引数 とは、任意の個数の値を受け取ることができる引数です。

Swiftでは、... を引数のあとに記述します。次の例では、複数の引数を許容する関数を定義しています。

// ... で可変長引数を受け取れるように定義する
func test(animals: String...) {
  for animal in animals {
    print(animal)
  }
}

test(animals: "cat")

/* 実行結果 */
// cat

test(animals: "cat", "dog", "rabbit")

/* 実行結果 */
// cat
// dog
// rabbit

最初の呼び出しでは一つだけ引数を指定しました。2番目の呼び出しでは、3つの引数を指定しています。このように、呼び出し元で引数の個数を任意に変えることができます。

# returnの省略 (暗黙的なreturn)

関数の内部実装が値の返却だけしかない場合は、returnキーワードを省略することができます。

func greeting(_ person: String) -> String {
  "Hi, \(person)!"
}

greeting("Tom") // Hi, Tom!

式を複数書くと、コンパイラはエラーを出力します。暗黙的なreturnは返却の実装のみに有効になります。

func greeting(_ person: String) -> String {
  print("Hello!")
  "Hi, \(person)!"
}

greeting("Tom")

// error: missing return in a function expected to return 'String'; did you mean to return // the last expression?
//   "Hi, \(person)!"
//   ^
//   return

# オーバーロード

Swiftでは、同名の関数を定義しようとするとコンパイラがエラーを出力します。

func test() {
  print("test1")
}

func test() {
  print("test2")
}

// error: invalid redeclaration of 'test()'
// func test() {

しかし、次の条件だと同名の関数でも定義をすることができます。

# 引数の個数が異なる

次の例では、引数の個数が異なるため同名の関数を定義できます。

func test(_ num: Int) {}

// 引数の個数が異なる
func test(_ num: Int, _ num2: Int) {}

# 引数の型が異なる

次の例では、引数の型が異なるため同名の関数を定義できます。

func test(_ num: Int) {}

// 引数の型が異なる
func test(_ num: String) {}

# 外部引数名が異なる

次の例では、外部引数名が異なるため同名の関数を定義できます。

func test(_ num: Int)  {}

// 外部引数名が異なる
func test(num1 num: Int)  {}

# 返り値の型が異なる

次の例では、返り値の型が異なるため同名の関数を定義できます。

func test(_ num: Int) -> Int { return num }

// 返り値の型が異なる
func test(_ num: Int) -> String { return "Hello" }