前を向くために Part3

プログラミング、音楽、外交問題、その他思いついたことを何でも公開

人生、前向きに生きたいもの。でも、何かと後ろ向きになりがちな自分がいるのです。前向きに生きるには、まず前を向かなければなりませぬ。じゃあ前を向くためにはどうしたらいいの?と日々悩んどります。これはその記録の一部です。

Swift言語ガイド 第6章 関数

  1. 関数には必ず名前がある。
    func sayHello( personName: String ) -> String {
        let greeting = "こんにちは、" + personName + "。"
        return greeting
    }
    println( sayHello( "あんな" ) )
    
  2. 引数がない場合でもかっこは必要。定義にも呼び出しにも。
    func sayHelloWorld() {
        println( "Hello, world" )
    }
    sayHelloWorld()
    
  3. 戻り値がない関数は、実は Void という型の戻り値を持っている。Void は空のタプルで、() と書く。
  4. 複数の戻り値がある関数を定義する場合は、戻り値にタプルを用いる。タプルの要素に名前をつけることもでき、その場合は関数の外でその名前が使える。
    func minMax( array: [ Int ] ) -> ( min: Int, max: Int ) {
        ...
    }
    println ( minMax.min( [ 1, 100, 1000 ]))
    
  5. オプショナルなタプルも使える。この場合、タプル全体がオプショナルとなる。
    func minMax( array: [ Int ] ) -> ( min: Int, max: Int )? {
        if array.isEmpty { return nil }
        ...
    }
    
  6. 外部引数名(External Parameter Names)とは、普通は関数内でしか見えない引数名を外部からも見えるようにする引数名で、関数呼び出し時(外部である)に使うことができる。こうすると1つの引数に2つの名前(外部名と内部名)がつくことになる。外部引数名を付ける時は、必ず外部引数名、空白、(通常の)内部引数名の順に書かなければならない。また、外部引数名を付ける時は、必ずそれを指定して引数にしなければならない。引数の順番に頼ってはいけないということである。
    func join( string s1: String, toString s2: String, withJoiner joiner: String ) -> String {
        return s1 + joiner + s2
    }
    let longString = join( string: "Hello", toString: "world", withJoiner: ", " )
    
  7. 外部引数名も内部引数名も同じでよいならば(つまり1つで済ませるならば)、引数名の直前にハッシュ(#)を付ければよい。
    func containsCharacter( #string: String, #character: Character ) -> Bool {
        for current in string {
            if current == character {
                return true
            }
        }
        return false
    }
    let hasCharacter = containsCharacter( string: "Hello", character: "o" )
    
  8. 引数にデフォルト値が定義してあれば、呼び出し時に引数を省略することができる。こういう引数は引数軍の最後にまとめた方がよい(必須ではないが)。
    func join( string s1: String, toString s2: String, withJoiner joiner: String = " " ) -> String {
        return s1 + joiner + s2
    }
    
  9. デフォルト値のある引数は、必ず外部名も存在する。コードで指定してあればそれが使われ、指定してなければ Swift が勝手に内部名と同じ外部名を付ける。一応、それが嫌なら外部名にアンダースコアを指定すればいいことになっているが、こうなってくると親切を通り越してお節介のようにも思えるのだが、言語仕様としてどうなんだろう? C の「簡潔に」という思想は、Swift には通用しないようだ。
    func join( s1: String, s2: String, joiner: String = " " ) {
        ...
    }
    join( "hello", "world", joiner: ", " )
    
  10. 可変長引数(Variadic Parameters)は、ゼロかそれ以上の値を受け付ける引数である。これを定義するには、引数の型名の後に ... をつける。これは関数内部ではその型の配列として見えるようになる。ただし、関数が持てる可変長引数は最大1個だけであり、常に引数リストの最後でなければならない。デフォルト値付き引き数よりも後である。
    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 )
    
  11. 可変引数(Variable Parameters)は引数定義に var をつける。こうすると、通常は関数内では変更できない引数が変更可能になる。ただし、関数の中だけで有効で、呼び出し元の(つまり外部の)変数の値までは変更できない。あくまでローカル変数である。
    func alignRight( var string: String, count: Int, pad: Character ) -> {
        string = padString + string
        ...
    }
    
  12. 可変引数とは異なり、In-Out 引数は引数の外部の値も変更可能つまり関数が終了した後も変更が残る。これを定義するには、引数定義に inout キーワードをつける。In-Out 引数に指定できるのは、外部において変数として宣言してあるものでなければならない。定数やリテラルは指定できない。また、呼び出し時に引数の直前に & を付ける必要がある。さらに、In-Out 引数はデフォルト値を持つことはできず、可変長引数にもできない。もちろん varlet も付けられない。
    func swapTwoInts( inout a: Int, inout b: Int ) {
        let temp = a
        a = b
        b = temp
    }
    var someInt = 3
    var anotherInt = 107
    swapTwoInts( &someInt, &anotherInt )
    
  13. 関数の型は、引数の型と戻り値の型からなる。関数を型とする定数や変数も宣言可能。
    func addTwoInts( a: Int, b: Int ) -> Int {
        return a + b
    }
    func multiplyTwoInts( a: Int, b: Int ) -> Int {
        return a * b
    }
    var mathFunc: ( Int, Int ) -> Int = addTwoInts
    mathFunc = multiplyTwoInts
    
  14. 関数には型があるので、型さえ合えば別の関数の引数になれる。
    func printMathResult( mathFunction: ( Int, Int ) -> Int, a: Int, b: Int ) {
        println( "結果: \( mathFunction( a, b ))" )
    }
    printMathResult( addTwoInts, 3, 5 )
    
  15. 同様に、関数の戻り値にもなる。
    func stepForward( input: Int ) -> Int {
        return input + 1
    }
    func stepBackward( input: Int ) -> Int {
        return input - 1
    }
    func chooseStepFunction( backwards: Bool ) -> ( Int ) -> Int {
        return backwards ? stepBackward : stepForward
    }
    
  16. 関数はネストできる。
    func chooseStepFunction( backwards: Bool ) -> ( Int ) -> Int {
        func stepForward( input: Int ) -> Int { return input + 1 }
        func stepBackward( input: Int ) -> Int { return input - 1 }
        return backwards ? stepBackward : stepForward
    }
    

(第6章 関数 終わり)