[Swift]Swift5.4で追加されたアップデートの紹介

今回は、Swift5.4 で追加された言語の機能の紹介を行いたいと思います。

すでにSwift5.5が発表されて今年の後半にリリースされるというアナウンスがされていますが、

今回はリリース済みの5.4について解説したいと思います。

今回の記事はSwift.org https://swift.org/blog/swift-5-4-released/を参考にしています。

追加された特徴

  • Support for multiple variadic parameters in functions, subscripts and initializers (SE-0284)
  • Extend implicit member syntax (SE-0287)
  • Result builders (SE-0289)
  • Local functions supporting overloading
  • Property wrappers for local variables

(SE-0287)Improved implicit member syntax

暗黙的なメンバ式の改善

  • 赤色を使いたい時にColor.redとしていたものを.redだけで描けるように

Swiftの暗黙的なメンバ式(enumとかのパラメーターを省略する記法)の使用を改善しています。

Swiftには、単純な表現に暗黙のメンバー構文を使用する機能が常にあります。例えば、SwiftUIでテキストに色を付けたい場合、Color.redではなく.redを使用できます。

import SwiftUI

struct ContentView1: View {
    var body: some View {
        Text("Hello, World!")
            .foregroundColor(.red) //本来ならばColor.red.opacity(0.5)としないといけない
    }
}

(SE-0284)Multiple variadic parameters in functions

  • 関数の引数やイニシャライザなどに可変パラメータ ...を使用することが可能に
  • ここでは可変パラメータのことをmultiple variadic parametersと言っている。

func summarizeGoals(times: Int..., players: String...) {}
timesの型は[Int] playersの型は[String]に暗黙的に変換される

利用例

import Foundation

func summarizeGoals(times: Int..., players: String...) {
    //timesの型は[Int] playersの型は[String]に暗黙的に変換される
    let joinedNames = ListFormatter.localizedString(byJoining: players)
    let joinedTimes = ListFormatter.localizedString(byJoining: times.map(String.init))
    
    print("\(times.count) goals where scored by \(joinedNames) at the follow minutes: \(joinedTimes)")
}

summarizeGoals(times: 18, 33, 55, 90,100, players: "Dani", "Jamie", "Roy")

SR-10069 Local functions now support overloading

  • ローカルで関数を呼ぶ前に関数をよぶことができるようになった。
    • Pythonなどは関数を先に定義しないと未定義になるやつ
  • 使用される型に基づいて実行するものを選択する。
    • ジェネリクスも考慮されている

利用例

func makeCookies2() {
//先に呼べる   
    add(item: Butter())
    add(item: Flour())
    add(item: Sugar())
//あとで宣言        
    func add(item: Butter) {
        print("Adding butter…")
    }
    
    func add(item: Flour) {
        print("Adding flour…")
    }
    
    func add(item: Sugar) {
        print("Adding sugar…")
    }
}
    
makeCookies2()

Creating variables that call a function of the same name

同名の関数を呼び出す変数の作成

  • 関数のローカルスコープで同じ名前を使うことができるようになった。

利用例

let username = "Taytay"

func suggestAlternativeUsername() -> String {
    var username = username
    username += String(Int.random(in: 1000...9999))
    return username
}

suggestAlternativeUsername()

(SE-0289)Result builders

あまり使ったことがないため詳しい説明は(SE-0289)を参照してください。

  • @resultBuilderを正式に実装
  • 結果をラップするプロパティーラッパーを使用することができる。
  • if文やfor文を使える

利用例

条件文も書ける

@resultBuilder
struct ConditionalStringBuilder {
    static func buildBlock(_ parts: String...) -> String {
        parts.joined(separator: "\n")
    }
        // 受け取った一番目の要素を取り出すことが可能
    static func buildEither(first component: String) -> String {
        return component
    }
        // 受け取った二番目の要素を取り出すことが可能 ない場合は無視
    static func buildEither(second component: String) -> String {
        return component
    }
}

Property wrappers are now supported for local variables

ローカル変数のプロパティラッパーがサポート

プロパティラッパーは、簡単で再利用可能な方法でプロパティに追加の機能を取り付ける方法として、Swift 5.1で初めて導入されましたが、Swift 5.4では、関数内のローカル変数としてそれらを使用することをサポートするために、その動作が拡張されました。

例えば、その値がゼロ以下にならないことを保証するプロパティラッパーを作成することができます。

利用例

@propertyWrapper struct NonNegative<T: Numeric & Comparable> {
    var value: T
    
    var wrappedValue: T {
        get { value }
    
        set {
            if newValue < 0 {
                value = 0
            } else {
                value = newValue
            }
        }
    }
    
    init(wrappedValue: T) {
        if wrappedValue < 0 {
            self.value = 0
        } else {
            self.value = wrappedValue
        }
    }
}

まとめ

今回はSwift5.4の新機能について紹介しました。

Swiftはリリースされてから時間がたっていますが(他の言語と比べたら若い)、
どんどん進化しています。この進化の要因として、SwiftUIがリリースされたことや、オープンソース化されていることが考察できます。

引き続きSwiftの情報を収集していきたいと思います!

Swift言語をより深く理解するためにAtcorderをやっています。よければ覗いてみてください

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です