SwiftとKotlinの構文比較 (1) 〜シンプルな値、制御フロー、関数とクロージャー

# はじめに

最近のKotlinの動向は熱いですよね。
特に[Androidの公式な開発言語になったこと](https://blog.jetbrains.com/kotlin/2017/05/kotlin-on-android-now-official/)と、[Spring 5が公式サポートしたこと](https://docs.spring.io/spring/docs/current/spring-framework-reference/languages.html#languages)はインパクトがあり、私もKotlinの学習を始めました。

この記事は私のような「Kotlinが気になっているSwiftプログラマー」向けです。
Apple公式のSwiftチュートリアル [A Swift Tour](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/GuidedTour.html#//apple_ref/doc/uid/TP40014097-CH2-ID1) を、Kotlinで書き替えてみました。

長くなったので記事を分けました。

**第一回（この記事）
　・シンプルな値
　・制御フロー
　・関数とクロージャー**

[第二回](https://qiita.com/y-some/items/286fb15fe8e0bd9aa5ef)
　・クラス
　・列挙体
　・構造体
　・プロトコル（インターフェイス）
　・拡張

# 前提バージョン

- Swift 4
- Kotlin 1.1

# Hello, World!

```swift:Swift
print("Hello, world!")
```

```kotlin:Kotlin
fun main(args: Array<String>) {
    println("Hello, world!")
}
```

どちらも`;`は不要です。私は素敵だと思います。:relaxed:


# シンプルな値

## 変数と定数

```swift:Swift
var myVariable = 42
myVariable = 50
let myConstant = 42
```

```kotlin:Kotlin
var myVariable = 42
myVariable = 50
val myConstant = 42
```

定数（再代入できない変数）は、Kotlinは`val`。

## 型推論と型宣言

```swift:Swift
let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70
```

```kotlin:Kotlin
val implicitInteger = 70
val implicitDouble = 70.0
val explicitDouble: Double = 70.0
```

近年開発された言語では、型宣言は後置が主流みたいですね。

Kotlinのデータ型についてはこちら。
[Kotlin Reference -Basic-Types](
https://kotlinlang.org/docs/reference/basic-types.html)

## 明示的な型変換

```swift:Swift
let label = "The width is "
let width = 94
let widthLabel = label + String(width)
```

```kotlin:Kotlin
val label = "The width is "
val width = 94
val widthLabel = label + width.toString()
```

Kotlinは、`val widthLabel = label + width`でもOKです。
Swiftとの比較のため、あえて上のように書きました。

## 文字列への変数の埋め込み

```swift:Swift
let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."
```

```kotlin:Kotlin
val apples = 3
val oranges = 5
val appleSummary = "I have ${apples} apples."
val fruitSummary = "I have ${apples + oranges} pieces of fruit."
```

## 複数の行を使用する文字列

```swift:Swift
let quotation = """
I said "I have \(apples) apples."
And then I said "I have \(apples + oranges) pieces of fruit."
"""
```

```kotlin:Kotlin
val quotation = """
I said "I have ${apples} apples."
And then I said "I have ${apples + oranges} pieces of fruit."
"""
```

## コレクション

```swift:Swift
var shoppingList = ["catfish", "water", "tulips", "blue paint"]
shoppingList[1] = "bottle of water"
print(shoppingList) // ["catfish", "bottle of water", "tulips", "blue paint"]

var occupations = [
    "Malcolm": "Captain",
    "Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"
print(occupations) // ["Malcolm": "Captain", "Jayne": "Public Relations", "Kaylee": "Mechanic"]
```

```kotlin:Kotlin
var shoppingList = mutableListOf("catfish", "water", "tulips", "blue paint")
shoppingList.set(1, "bottle of water")
println(shoppingList)  // [catfish, bottle of water, tulips, blue paint]

var occupations = mutableMapOf(
    "Malcolm" to "Captain",
    "Kaylee" to "Mechanic"
)
occupations.set("Jayne", "Public Relations")
println(occupations) // {Malcolm=Captain", Kaylee=Mechanic, Jayne=Public Relations}
```

Kotlinのコレクションは仕様的にJVMの制約を引きずっているようですし、JavaのコレクションAPIも使えるので、使いこなすにはそれなりの学習が必要そうです。:sweat_smile:
[Kotlin Reference -Collections](https://kotlinlang.org/docs/reference/collections.html)
[Kotlinコレクション入門](https://qiita.com/opengl-8080/items/4d335dafe526dd17d96e)

# 制御フロー

## forループとif文

```swift:Swift
let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {
    if score > 50 {
        teamScore += 3
    } else {
        teamScore += 1
    }
}
print(teamScore) // 11
```

```kotlin:Kotlin
val individualScores = listOf(75, 43, 103, 87, 12)
var teamScore = 0
for (score in individualScores) {
    if (score > 50) {
        teamScore += 3
    } else {
        teamScore += 1
    }
}
println(teamScore) // 11
```

Kotlinの条件式は`( )`が必須です。
SwiftもKotlinもCスタイルのループ`for (Int i = 0; i < n; i++)`は廃止されています。
Swiftは`i++`、`++i`、`i--`、`--i`の演算子は廃止されていますが、Kotlinでは使えます。

## while文

```swift:Swift
var n = 2
while n < 100 {
    n *= 2
}
print(n) // 128

var m = 2
repeat {
    m *= 2
} while m < 100
print(m) // 128
```

```kotlin:Kotlin
var n = 2
while (n < 100) {
    n *= 2
}
println(n) // 128

var m = 2
do {
    m *= 2
} while (m < 100)
println(m) // 128
```

## Null Safety

```swift:Swift
var optionalString: String? = "Hello"
print(optionalString == nil) // false
 
var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
    greeting = "Hello, \(name)"
    println(greeting) // Hello, John Appleseed
}
```

```kotlin:Kotlin
var optionalString: String? = "Hello"
println(optionalString == null) // false
 
var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
optionalName?.let {
    val name = it
    greeting = "Hello, ${name}"
    print(greeting) // Hello, John Appleseed
}
```

SwiftのOptionalはKotlinではNullableと呼びます。
Kotlinの`it`はなかなかイケてると思いました。

```swift:Swift
let nickName: String? = nil
let fullName: String = "John Appleseed"
let informalGreeting = "Hi \(nickName ?? fullName)"
print(informalGreeting) // Hi John Appleseed
```

```kotlin:Kotlin
val nickName: String? = null
val fullName: String = "John Appleseed"
val informalGreeting = "Hi ${nickName ?: fullName}"
println(informalGreeting) // Hi John Appleseed
```

Kotlinコードの`?:`は[Elvis構文](https://kotlinlang.org/docs/reference/null-safety.html#elvis-operator)と呼びます。

## switch文

```swift:Swift
let vegetable = "red pepper"
switch vegetable {
case "celery":
    print("Add some raisins and make ants on a log.")
case "cucumber", "watercress":
    print("That would make a good tea sandwich.")
case let x where x.hasSuffix("pepper"):
    print("Is it a spicy \(x)?")
default:
    print("Everything tastes good in soup.")
}
// Is it a spicy red pepper?
```

```kotlin:Kotlin
val vegetable = "red pepper"
when (vegetable) {
    "celery" ->
        println("Add some raisins and make ants on a log.")
    "cucumber", "watercress" ->
        println("That would make a good tea sandwich.")
    else -> {
        if (vegetable.endsWith("pepper")) {
            println("Is it a spicy ${vegetable}?")    
        } else {
            println("Everything tastes good in soup.")
        }
    }
}
```
Kotlinのswitch文は、Swiftほどは、多種多様な比較演算をサポートしていないようです。

KotlinもSwiftと同様に、Javaのように`break;`を書かなくてもフォールスルーしません。
コードが簡潔になって良いですよね。


# 関数とクロージャー

## 関数の基本構文

```swift:Swift
func greet(person: String, day: String) -> String {
    return "Hello \(person), today is \(day)."
}
print(greet(person: "Bob", day: "Tuesday")) // Hello Bob, today is Tuesday.
```

```kotlin:Kotlin
fun greet(person: String, day: String): String {
    return "Hello ${person}, today is ${day}."
}
println(greet(person = "Bob", day = "Tuesday")) // Hello Bob, today is Tuesday.
```

Kotlinも名前付きパラメータを取り入れています。
パラメータ名を省略する場合、Swiftでは関数側で`_`によって省略することを宣言しますが、Kotlinでは、以下のように呼び元側で省略します。

```swift:Swift
func greet(_ person: String, on day: String) -> String {
    return "Hello \(person), today is \(day)."
}
print(greet("John", on: "Wednesday")) // Hello John, today is Wednesday.
```

```kotlin:Kotlin
fun greet(person: String, day: String): String {
    return "Hello ${person}, today is ${day}."
}
println(greet("Bob", day = "Tuesday")) // Hello Bob, today is Tuesday.
```

Swiftはパラメータ変数名と引数のラベルを別の名前にできますが、Kotlinにはその機能はないようです。

## タプル

Kotlinでは古いバージョンにはタプルがあったようですが、バージョンアップ時に削除されたとのこと。
（参考）https://blog.jetbrains.com/kotlin/2016/12/kotlin-1-1-m04-is-here/
値が2つだけの`Pair`という形では残っています。
[Kotlin -Pair](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-pair/index.html)

## 関数のネスト

```swift:Swift
func returnFifteen() -> Int {
    var y = 10
    func add() {
        y += 5
    }
    add()
    return y
}
print(returnFifteen()) // 15
```

```kotlin:Kotlin
fun returnFifteen() : Int {
    var y = 10
    fun add() {
        y += 5
    }
    add()
    return y
}
println(returnFifteen()) // 15
```

どちらも、内部関数から外部関数のローカル変数（つまりクロージャ）に対し演算することができます。

## 高階関数

```swift:Swift
func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {
    for item in list {
        if condition(item) {
            return true
        }
    }
    return false
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(list: numbers, condition: {(number: Int) -> Bool in return number < 10})
// true
```

```kotlin:Kotlin
fun hasAnyMatches(list: List<Int>, condition: (Int) -> Boolean) : Boolean {
    for (item in list) {
        if (condition(item)) {
            return true
        }
    }
    return false
}
var numbers = listOf(20, 19, 7, 12)
hasAnyMatches(list = numbers, condition = fun(number: Int) : Boolean {return number < 10})
// true 
```

どちらも関数は第一級オブジェクトです。
関数の引数で無名関数を渡したり、戻り値として関数を受け取ったりは、どちらでもシンプルに書けます。

第二回はこちらです。
[SwiftとKotlinの構文比較 (2) 〜クラス、列挙体、構造体、プロトコル、拡張](https://qiita.com/y-some/items/286fb15fe8e0bd9aa5ef)