【Swift入門 #18】コードを再利用する - 関数の基本と定義方法

プログラムを部品化して再利用可能にする関数について、基本的な定義方法と呼び出し方を初心者向けに解説します。

📚 Swift入門シリーズ: #16 guard文#17 オプショナル型


前回はオプショナル型による安全なnil処理を学びました。今回は、コードを再利用可能にする関数について学びましょう。

著者
著者: Sera
大学院でAI作曲に関して研究中!
来春からデータサイエンティストとして働く予定の技術オタク。
初心者
登場人物: あかり
流行りのAIやWeb技術に興味津々!
『知りたい』気持ちで質問を止められない、好奇心旺盛な学生。
normalの表情
初心者

前回はオプショナル型でnilを安全に扱う方法を学んだね!

専門家

そうだね。今回からは、第7章:関数 について学んでいくよ。関数は、プログラムを整理して再利用可能にするための重要な機能なんだ。

confusedの表情
初心者

関数って何?これまでも print() とか使ってきたけど、それも関数なの?

専門家

その通り!print() も関数なんだ。関数 は、特定の処理をまとめて名前を付けたもので、必要な時に呼び出して使えるんだよ。

関数とは

専門家

これまで、同じような処理を何度も書いてきたよね。例えば、こんなコードがあったとしよう。

// ユーザーAの挨拶
let nameA = "田中"
print("こんにちは、\(nameA)さん")
print("今日も良い一日を!")

// ユーザーBの挨拶
let nameB = "佐藤"
print("こんにちは、\(nameB)さん")
print("今日も良い一日を!")

// ユーザーCの挨拶
let nameC = "鈴木"
print("こんにちは、\(nameC)さん")
print("今日も良い一日を!")

同じようなコードを何度も書いているよね。これを 関数 にまとめることで、再利用できるようになるんだ。

excitedの表情
初心者

それは便利そう!

関数の基本的な書き方

専門家

関数の基本的な書き方はこうなるよ。

func 関数名() {
    // 処理
}

func は「function(関数)」の略なんだ。実際の例を見てみよう。

func greet() {
    print("こんにちは")
    print("今日も良い一日を!")
}

これで greet という名前の関数が定義できたんだ。

confusedの表情
初心者

でも、これだけだと何も起きないよね?

専門家

その通り!関数を定義しただけでは実行されないんだ。関数を 呼び出す 必要があるんだよ。

func greet() {
    print("こんにちは")
    print("今日も良い一日を!")
}

// 関数を呼び出す
greet()
// こんにちは
// 今日も良い一日を!

greet() で関数を呼び出すと、関数の中の処理が実行されるんだ。

関数は何度でも呼び出せる

専門家

関数は何度でも呼び出せるんだよ。

func greet() {
    print("こんにちは")
}

greet()  // こんにちは
greet()  // こんにちは
greet()  // こんにちは

1回定義すれば、何度でも使えるんだ。これが関数の大きなメリットなんだよ。

パラメータ(引数)

confusedの表情
初心者

でも、さっきの挨拶の例だと、名前を変えたいんだけど...

専門家

いい質問だね!関数に パラメータ(引数) を渡すことで、動的に値を変えられるんだ。

func greet(name: String) {
    print("こんにちは、\(name)さん")
    print("今日も良い一日を!")
}

(name: String) がパラメータなんだ。「String型のnameという値を受け取る」という意味だよ。

excitedの表情
初心者

じゃあ、呼び出すときに名前を渡せばいいの?

専門家

その通り!

func greet(name: String) {
    print("こんにちは、\(name)さん")
    print("今日も良い一日を!")
}

greet(name: "田中")
// こんにちは、田中さん
// 今日も良い一日を!

greet(name: "佐藤")
// こんにちは、佐藤さん
// 今日も良い一日を!

greet(name: "鈴木")
// こんにちは、鈴木さん
// 今日も良い一日を!

同じ関数を使って、異なる名前で挨拶できるんだ。これで最初のコードがずっと短くなったね。

複数のパラメータ

専門家

パラメータは複数指定できるんだよ。

func greet(name: String, time: String) {
    print("\(time)、\(name)さん")
}

greet(name: "田中", time: "おはようございます")
// おはようございます、田中さん

greet(name: "佐藤", time: "こんばんは")
// こんばんは、佐藤さん

カンマで区切って、複数のパラメータを定義できるんだ。

normalの表情
初心者

パラメータの順番は大事なの?

専門家

Swiftでは、パラメータ名を指定して呼び出すから、順番を間違えることは少ないんだ。でも、定義したパラメータ名と同じ名前で渡す必要があるよ。

func introduce(name: String, age: Int) {
    print("私は\(name)です。\(age)歳です。")
}

introduce(name: "田中", age: 25)
// 私は田中です。25歳です。

// introduce(age: 25, name: "田中")  // 順番を変えても動作するが、推奨されない

パラメータ名と引数ラベル

専門家

Swiftの関数には、引数ラベルパラメータ名 という2つの名前があるんだ。

func greet(to name: String) {
    print("こんにちは、\(name)さん")
}

greet(to: "田中")

to が引数ラベル(外部名)で、name がパラメータ名(内部名)なんだ。

  • 引数ラベル: 関数を呼び出すときに使う名前
  • パラメータ名: 関数の中で使う名前

引数ラベルを付けることで、関数の呼び出しが自然な英文のように読めるんだよ。

confusedの表情
初心者

いつもこうしなきゃダメなの?

専門家

いや、引数ラベルを省略することもできるんだ。_(アンダースコア)を使うんだよ。

func greet(_ name: String) {
    print("こんにちは、\(name)さん")
}

greet("田中")  // 引数ラベルなしで呼び出せる

引数ラベルを _ にすると、呼び出し時に引数名を書かなくて良くなるんだ。

戻り値(return)

confusedの表情
初心者

関数って、処理を実行するだけなの?計算結果を返したりできないの?

専門家

できるよ!関数は 戻り値 を返すことができるんだ。return を使うんだよ。

func add(a: Int, b: Int) -> Int {
    return a + b
}

let result = add(a: 3, b: 5)
print(result)  // 8

-> Int は「Int型の値を返す」という意味なんだ。return a + b で、計算結果を返しているよ。

happyの表情
初心者

これは便利!関数から値を受け取れるんだね!

専門家

そうなんだ。もう少し実用的な例を見てみよう。

func isAdult(age: Int) -> Bool {
    if age >= 18 {
        return true
    } else {
        return false
    }
}

let age = 20
if isAdult(age: age) {
    print("成人です")
} else {
    print("未成年です")
}
// 成人です

Bool型を返す関数で、年齢が18歳以上かどうかを判定しているんだ。

この関数は、もっと短く書くこともできるよ。

func isAdult(age: Int) -> Bool {
    return age >= 18
}

// さらに短く
func isAdult(age: Int) -> Bool {
    age >= 18  // returnを省略できる
}

関数の本体が1行だけの場合、return を省略できるんだ。

複数の値を返す(タプル)

専門家

タプルを使えば、複数の値を返すこともできるんだ。

func getMinMax(numbers: [Int]) -> (min: Int, max: Int) {
    var min = numbers[0]
    var max = numbers[0]

    for number in numbers {
        if number < min {
            min = number
        }
        if number > max {
            max = number
        }
    }

    return (min, max)
}

let result = getMinMax(numbers: [3, 7, 2, 9, 4])
print("最小値: \(result.min)")  // 最小値: 2
print("最大値: \(result.max)")  // 最大値: 9

タプルを使って、最小値と最大値を同時に返しているんだよ。

戻り値がない関数

専門家

戻り値がない関数は、戻り値の型を書かないか、-> Void と書くんだ。

// 戻り値の型を書かない(推奨)
func greet(name: String) {
    print("こんにちは、\(name)さん")
}

// -> Void と明示的に書く
func greet(name: String) -> Void {
    print("こんにちは、\(name)さん")
}

どちらも同じ意味なんだけど、通常は戻り値の型を書かない方が一般的だよ。

オプショナルの戻り値

専門家

関数の戻り値もオプショナルにできるんだ。

func findUser(id: Int) -> String? {
    if id == 1 {
        return "田中"
    } else if id == 2 {
        return "佐藤"
    } else {
        return nil
    }
}

if let user = findUser(id: 1) {
    print("ユーザー: \(user)")
} else {
    print("ユーザーが見つかりません")
}
// ユーザー: 田中

if let user = findUser(id: 99) {
    print("ユーザー: \(user)")
} else {
    print("ユーザーが見つかりません")
}
// ユーザーが見つかりません

-> String? で、String型のオプショナルを返すことを示しているんだ。見つからない場合はnilを返せるんだよ。

デフォルト引数値

専門家

パラメータに デフォルト値 を設定できるんだ。

func greet(name: String, greeting: String = "こんにちは") {
    print("\(greeting)、\(name)さん")
}

greet(name: "田中")
// こんにちは、田中さん

greet(name: "佐藤", greeting: "おはようございます")
// おはようございます、佐藤さん

greeting: String = "こんにちは" で、デフォルト値を設定しているんだ。呼び出し時に省略すると、デフォルト値が使われるんだよ。

happyの表情
初心者

これは便利!よく使う値をデフォルトにしておけるんだね!

関数の命名規則

専門家

関数名にも、命名規則があるんだ。

良い関数名:

  • 動詞で始める(何をするかが分かる)
  • 分かりやすく具体的にする
  • キャメルケースを使う
// 良い例
func calculateTotal(price: Int, quantity: Int) -> Int {
    return price * quantity
}

func isValidEmail(email: String) -> Bool {
    return email.contains("@")
}

func printUserInfo(name: String, age: Int) {
    print("\(name)さん(\(age)歳)")
}

悪い関数名:

// 悪い例
func calc(p: Int, q: Int) -> Int {  // 短すぎる、意味不明
    return p * q
}

func x(email: String) -> Bool {  // 何をするか分からない
    return email.contains("@")
}

func data(n: String, a: Int) {  // 動詞がない、パラメータ名が不明瞭
    print("\(n)さん(\(a)歳)")
}

実践練習

専門家

じゃあ、練習問題をやってみよう。

問題1: 2つの整数を受け取って、大きい方を返す関数 max を作ってみて。

excitedの表情
初心者

やってみる!

func max(a: Int, b: Int) -> Int {
    if a > b {
        return a
    } else {
        return b
    }
}

print(max(a: 5, b: 3))   // 5
print(max(a: 2, b: 8))   // 8

できた!

専門家

完璧だね!もっと短く書くこともできるよ。

func max(a: Int, b: Int) -> Int {
    return a > b ? a : b
}

// さらに短く
func max(a: Int, b: Int) -> Int {
    a > b ? a : b
}

三項条件演算子を使って、1行で書けるんだ。

happyの表情
初心者

すごい!短い!

専門家

問題2: 配列の中から偶数だけを抽出して新しい配列を返す関数 filterEvenNumbers を作ってみて。

normalの表情
初心者
func filterEvenNumbers(numbers: [Int]) -> [Int] {
    var evenNumbers: [Int] = []

    for number in numbers {
        if number % 2 == 0 {
            evenNumbers.append(number)
        }
    }

    return evenNumbers
}

let numbers = [1, 2, 3, 4, 5, 6, 7, 8]
let evens = filterEvenNumbers(numbers: numbers)
print(evens)  // [2, 4, 6, 8]

こう?

専門家

素晴らしい!完璧だよ。配列を作って、偶数だけを追加して返しているね。関数の使い方をしっかり理解できているよ。

ちなみに、guardを使った書き方もできるよ。

func filterEvenNumbers(numbers: [Int]) -> [Int] {
    var evenNumbers: [Int] = []

    for number in numbers {
        guard number % 2 == 0 else {
            continue
        }
        evenNumbers.append(number)
    }

    return evenNumbers
}

どちらの書き方も正しいから、読みやすい方を選べばいいよ。

まとめ

この記事では、関数の基本について学びました。

関数の定義:

  • func 関数名() { 処理 }
  • 処理をまとめて名前を付ける
  • 何度でも呼び出せる

パラメータ:

  • func 関数名(パラメータ名: 型) { 処理 }
  • 関数に値を渡せる
  • 複数のパラメータも可能
  • デフォルト値を設定できる

戻り値:

  • func 関数名() -> 型 { return 値 }
  • 計算結果を返せる
  • オプショナルも返せる
  • タプルで複数の値を返せる
  • 1行の場合、returnを省略できる

命名規則:

  • 動詞で始める
  • 分かりやすく具体的に
  • キャメルケースを使う

次回は「関数の引数」として、引数ラベル、可変長引数、inoutパラメータなど、さらに高度な関数の使い方を学びます!

← ブログ一覧に戻る