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

はじめに

最近のKotlinの動向は熱いですよね。
特にAndroidの公式な開発言語になったことと、Spring 5が公式サポートしたことはインパクトがあり、私もKotlinの学習を始めました。

この記事は私のような「Kotlinが気になっているSwiftプログラマー」向けです。
Apple公式のSwiftチュートリアル A Swift Tour を、Kotlinで書き替えてみました。

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

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

第二回
 ・クラス
 ・列挙体
 ・構造体
 ・プロトコル(インターフェイス)
 ・拡張

前提バージョン

  • Swift 4
  • Kotlin 1.1

Hello, World!

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

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

シンプルな値

変数と定数

Swift
var myVariable = 42
myVariable = 50
let myConstant = 42
Kotlin
var myVariable = 42
myVariable = 50
val myConstant = 42

定数(再代入できない変数)は、Kotlinはval

型推論と型宣言

Swift
let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70
Kotlin
val implicitInteger = 70
val implicitDouble = 70.0
val explicitDouble: Double = 70.0

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

Kotlinのデータ型についてはこちら。
Kotlin Reference -Basic-Types

明示的な型変換

Swift
let label = "The width is "
let width = 94
let widthLabel = label + String(width)
Kotlin
val label = "The width is "
val width = 94
val widthLabel = label + width.toString()

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

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

Swift
let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."
Kotlin
val apples = 3
val oranges = 5
val appleSummary = "I have ${apples} apples."
val fruitSummary = "I have ${apples + oranges} pieces of fruit."

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

Swift
let quotation = """
I said "I have \(apples) apples."
And then I said "I have \(apples + oranges) pieces of fruit."
"""
Kotlin
val quotation = """
I said "I have ${apples} apples."
And then I said "I have ${apples + oranges} pieces of fruit."
"""

コレクション

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
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
Kotlinコレクション入門

制御フロー

forループとif文

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
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++++ii----iの演算子は廃止されていますが、Kotlinでは使えます。

while文

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
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
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
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
let nickName: String? = nil
let fullName: String = "John Appleseed"
let informalGreeting = "Hi \(nickName ?? fullName)"
print(informalGreeting) // Hi John Appleseed
Kotlin
val nickName: String? = null
val fullName: String = "John Appleseed"
val informalGreeting = "Hi ${nickName ?: fullName}"
println(informalGreeting) // Hi John Appleseed

Kotlinコードの?:Elvis構文と呼びます。

switch文

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
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ほどは、多種多様な比較演算をサポートしていないようです。
またSwiftは上のコードのdefault:を削除すると、比較漏れがあるということでコンパイルエラーになりますが、Kotlinにはそのような言語機能は無いようです。

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

関数とクロージャー

関数の基本構文

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
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
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
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

関数のネスト

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

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

高階関数

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
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) 〜クラス、列挙体、構造体、プロトコル、拡張


『 Swift 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。