Kotlin入門:関数

実際に読んでみて良かった書籍について情報を発信していますので、
よろしければ[Twitter](https://twitter.com/KaoruTojo_Novel)のフォローもお願いします。
##関数
関数を定義するにはfun命令を使用する。

構文

```Kotlin
function name(param: ptype, ...): rtype{
    statements
}
```

name:関数名
param:仮引数
ptype:仮引数のデータ型
rtype:戻り値のデータ型
statements:処理内容

入力例

```Kotlin
fun main(){
    println(say("Hello"))
}
fun say(str:String): String{
    return str
}
```

実行すると以下の通りになります。

```Kotlin
Hello
```

関数に戻り値がない場合には**Unit**を使います。

```Kotlin
fun main(){
    sayHello()
}
fun sayHello(): Unit{
    println("Hello")
}
```

以下のように**Unit**を省略することもできます。

```Kotlin
fun main(){
    sayHello()
}
fun sayHello(){
    println("Hello")
}
```

###引数の既定値
既定値とは、関数の呼び出し時、引数を省略した場合に渡される値のことです。

```Kotlin
fun main(){
    sayHello()
}
fun sayHello(str :String = "Hello"){
    println(str)
}
```
実行すると以下の通りになります。

```Kotlin
Hello
```

以下のように引数を指定して実行すると

```Kotlin
fun main(){
    sayHello("Hello World")
}
fun sayHello(str :String = "Hello"){
    println(str)
}
```
結果は以下の通りになります。

```Kotlin
Hello World
```

また、既定値には他の引数や関数を指定することもできます。
引数を指定した場合は以下の通りです。

```Kotlin
fun main(){
    sayHello()
}
fun sayHello(str1 :String = "Hello ",str2 :String = str1){
    println(str1 + str2)
}
```

実行すると結果は以下の通りになります。

```Kotlin
Hello Hello 
```

ただし、他の引数を既定値とする場合には、自身よりも前に定義された引数だけ可能です。
関数を指定した場合は以下の通りです。

```Kotlin
fun main(){
    sayHello()
}
fun sayHello(str1 :String = "Hello ",str2 :String = sayWorld()){
    println(str1 + str2)
}
fun sayWorld():String{
    return "World"
}
```

実行すると結果は以下の通りになります。

```Kotlin
Hello World
```

###名前付き引数
関数を呼び出すとき、()内を「仮引数名=値」の形式とすることが可能です。
名前付き引数を利用すると
・値を識別しやすい
・必要な引数だけを記述できる
などのメリットがあります。

引数の個数が多いときは有効な記法です。
以下は入力例です。

```Kotlin
fun main(){
    sayHello(str2 = "good",str1 = "very ")
}
fun sayHello(str1 :String = "Hello ",str2 :String){
    println(str1 + str2)
}
```

実行すると結果は以下の通りになります。

```Kotlin
very good
```

必要な引数のみを記述した場合は以下の通りです。

```Kotlin
fun main(){
    sayHello(str2 ="World")
}
fun sayHello(str1 :String = "Hello ",str2 :String){
    println(str1 + str2)
}
```


###名前付き引数と通常の引数
名前付き引数と名前なし引数（通常の引数）は混在させることが可能です。
ただし、この場合には名前付き引数は通常の引数より後方に記述しなければなりません。

```Kotlin
fun main(){
    sayHello("very ",str2 ="good")
}
fun sayHello(str1 :String = "Hello ",str2 :String){
    println(str1 + str2)
}
```
以上を実行すると結果は以下の通りになります。

```Kotlin
very good
```

以下を実行するとエラーになります。

```Kotlin
fun main(){
    sayHello(str1 = "very ","good")
}
fun sayHello(str1 :String = "Hello ",str2 :String){
    println(str1 + str2)
}
```

###可変長引数
仮引数に`vararg`キーワードをつけると可変長引数を表現できます。
可変長引数は内部的に配列とみなされます。
そのため`for`命令で処理することが可能です。

```Kotlin
fun main(){
    println(list("山田 ","太朗"))
}
fun list(vararg names:String):String{
    var result = "前"
    for(name in names){
        result += name
    }
    return result
}
```
実行すると結果は以下の通りです。

```Kotlin
前山田 太朗
```

可変長引数と通常の引数は混在できますが、
原則として可変長引数は引数リストの末尾で宣言するようにしましょう。
可変長引数が末尾でない場合、通常の引数は名前付き引数にしなければならなくなります。

以下は可変長引数と通常の引数は混在した例です。
※ honorificは敬称という意味です。

```Kotlin
fun main(){
    println(list("山田 ","太朗",honorific = "さん"))
}
fun list(vararg names:String,honorific:String):String{
    var result = "前"
    for(name in names){
        result += name
    }
    return result + honorific
}
```

実行結果は以下の通りです。

```Kotlin
前山田 太朗さん
```
もし、可変長引数の後が名前付き引数でなければ、
どこまでが可変長引数の範囲内なのかを判断できないのでエラーになります。

可変長引数を末尾にした場合は以下の通りです。

```Kotlin
fun main(){
    println(list("さん","山田 ","太朗"))
}
fun list(honorific:String,vararg names:String):String{
    var result = "前"
    for(name in names){
        result += name
    }
    return result + honorific
}
```

実行結果は以下の通りです。

```Kotlin
前山田 太朗さん
```

####可変長引数に配列を渡すには
可変長引数に配列を渡すにはスプレッド演算子(*)を使用します。

```Kotlin
fun main(){
    var values = arrayOf("山田 ","太朗","さん")
①  println(list(values))
②  println(list(*values))
}
fun list(vararg names:String):String{
    var result = "前"
    for(name in names){
        result += name
    }
    return result
}
```

①ではエラーになります。
②ではエラーになりません。


##複数の戻り値を指定

複数の戻り値を指定することができます。
Pair(２つの値)、Triple(３つの値)を利用できます。

```Kotlin
fun main(){
    val(last,first) = getNames("山田","太朗")
    println(last)
    println(first)
}
fun getNames(last:String,first:String):Pair<String,String>{
    return Pair(last,first)
}
```
実行結果は以下の通りです。

```Kotlin
山田
太朗
```

TripleはPairと用法がほぼ同じなため割愛します。