Menu

Category

Archive

logo


The Swift Programming Language ~ Functions

2014-06-09 17:00:00 +0900
  • このエントリーをはてなブックマークに追加

iBooks にある “The Swift Programming Language” の勉強メモ。Objective-C と C を普段書いている自分から、ちょっと馴染みがないものを特にまとめておきます。目次は こちら

今回は、Function に関して。長いので 後編 はこちら。

Function

1. 複数の返り値

以前、Tuple についてみたように、関数は C と違い、いくつかの値を返すことができます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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)
}

最後の return 文 が tuple。

1
2
3
let total = count("some arbitrary string!")
println("\(total.vowels) vowels and \(total.consonants) consonants")
// prints "6 vowels and 13 consonants

ここでは、count 関数の中で定義されているため、total tuple に対してそれぞれの名前を定義する必要はありません。

2. External Parameter Name

関数を呼ぶ際に、もっと説明的にするために、外的に引数に対して名前を付けることができます。

1
2
3
func join(s1: String, s2: String, joiner: String) -> String {
    return s1 + joiner + s2
}

この関数は、External Parameter Name がない普通の関数です。この関数を呼ぶ際には、

1
join("hello", "world", ", ")

とします。これだけだと、3つの String を渡す時に、それぞれどのような役割を持った String を持つのか分かりにくいです。特に第三者がコードを読む際に、あまり親切ではありません。それらを明示的に示すのが External Parameter Name です。

1
2
3
4
func join(string s1: String, toString s2: String, withJoiner joiner: String)
    -> String {
        return s1 + joiner + s2
}

この External Parameter Name の例は、s1 に対して、string。s2 に対して、toString。joiner に対して、withJoiner という External Parameter Name をつけています。s1 の類の変数名を、local parameter name と呼び、関数の中で使います。また、関数の中でのみ有効です。この関数を呼ぶ際には、Objective-C みたいに下記のように書きます。

1
2
join(string: "hello", toString: "world", withJoiner: ", ")
// returns "hello, world”

External Parameter Name を定義した場合、関数を呼ぶ際には、必ず External Parameter Name もつけなければいけません。

3. External Parameter Name の省略した書き方

もし、External Parameter Name も Local Parameter Name も同じ名前であればよい時には、関数を定義する際に少し簡単に書くことができます。

1
2
3
4
5
6
7
8
func containsCharacter(#string: String, #characterToFind: Character) -> Bool {
    for character in string {
        if character == characterToFind {
            return true
        }
    }
    return false
}

この #parameterName という書式を使うことで、External Parameter Name と Local Parameter Name を同時に定義できます。

1
2
let containsAVee = containsCharacter(string: "aardvark", characterToFind: "v")
// containsAVee equals true, because "aardvark" contains a "v”

4. 引数のデフォルト値

デフォルトで使われる引数の値を関数定義時に指定できます。関数呼び出し時に、その引数が省略された場合には、そのデフォルト値が自動的に使用されます。

1
2
3
4
func join(string s1: String, toString s2: String,
    withJoiner joiner: String = " ") -> String {
        return s1 + joiner + s2
}

まずは、普通の呼び方。

1
2
join(string: "hello", toString: "world", withJoiner: "-")
// returns "hello-world"

デフォルト値を使用する場合。

1
2
join(string: "hello", toString: "world")
// returns "hello world”

引数のデフォルト値を定義する際は、関数定義の引数リストの最後に書くようにします。このことにより、デフォルト値がない引数をいつも同じ順番で書け、コードが読みやすくなります。

5. External Parameter Name とデフォルト値

関数の引数にデフォルトを使用する場合に、Swift は自動的に External Parameter Name を定義してくれます。例えば、

1
2
3
func join(s1: String, s2: String, joiner: String = " ") -> String {
    return s1 + joiner + s2
}

と joiner に対して自動的に同じ名前の External Parameter Name が定義されています。joiner はデフォルト値を持っているためです。そのため、関数を呼ぶ際には、

1
2
3
4
5
join("hello", "world", joiner: "-")
// returns "hello-world
// or 
join("hello", "world")
// return "hello world"

デフォルト値を持つ引数を関数に渡す際には、External Parameter Name を省略できません。もし、どうしても External Parameter Name を使いたくない時には、_ を関数定義時に追加することで Swift が自動的に External Parameter Name を定義するのを防ぐことができます。しかし、基本的に、デフォルト値を持つ引数に External Parameter Name はあった方がよいようです。

1
2
3
4
func join(s1: String, s2: String, _ joiner: String = " ") -> String {
    return s1 + joiner + s2
}        
join("hello", "world", "-") // now, you can do this