Tana Gone
Tana Gone
1 min read

Categories

Tags

初見殺しのSwiftヘンテコ構文

Void, Emptyって何?

まず、Void。これは空のTuple、戻値無しを意味する。Swiftでは戻値無しを空のTupleで代用するのだ。下記の(1)の部分はClosureを格納する配列を意味する。

(2)の部分は、関数の引数が引数/戻値ペアが()->Voidである事を示す。関数本体部分では受取ったClosureを引数名を使って呼出している。

// 初見殺しのヘンテコ変数初期化, que: 関数格納配列のinitializer呼出し
var que = [()->Void]() // (1)

func enque(ope: @escaping ()->Void) { // (2)                                    
  que.append(ope)
}

enque { print("executed") }
enque { print("more exec") }
que.forEach { $0() }

実行すると

executed
more exec

となる。

func foo() { 
  fatalError("fatal") 
  print("Never stop") 
} 

これをコンパイルすると、警告、注意が出る。

warning: will never be executed                                                                             
  print("Never stop")
        ^
note: a call to a never-returning function
  fatalError("fatal")

戻って来ないと注意されるんだけど、それを明示的に示す次のコードを付けても警告、注意は無くならない。@Swift5.1

func foo() -> Never {
  fatalError("fatal")
  print("Never stop")
} 

正直Neverの使いどころがよく解らん。Result<Void, Never>とかってどこかで見た様な気がする。

引数付きClosureを取る関数の書き方

下記ソースではClosureを定義して呼出している。呼出し時には型指定e:Intは不要。eで問題無し。

func create(_ handler: (Int) -> Void) {
  handler(1) // closureはhandlerという名でアクセス
}
create( {(e:Int) in print(e) } ) // => 1

値付き列挙子を持つenum

名前付きタイプの中でもenumがC言語とは大きく異なっている。下記のコードは型パラメータElement付きのenum Eventを定義して、列挙子nextに1を付与してインスタンス化している。

public enum Event<Element> {
    case next(Element)
    case error(Error)
    case completed
}
let a:Event<Int> = Event.next(1)
print(a) // => next(1)

case文は、次の様に横に書ける

enum Kolor {
  case red, blue, green
}
let b = Kolor.red
print(b) // => red

func付きenumを定義して呼び出してみる。

// func付きenum
enum SKolor {
  case red, blue, green
  func action() {
    switch self {
      case .red:
        print("red")
       
      default:
        print("other")
    }
  }   
}       
let c = SKolor.blue
c.action() // => next(1)

keyPathリテラル

\.nameとかっていきなりbackslashから始まって何だ?Swift5からkeyPathリテラルって機能が付加されている。要するにプロパティーへのアクセスを記述する方法らしい。

import Foundation
class Person: NSObject {
      @objc dynamic var name: String
  
      init(name: String) {
          self.name = name
      }
  }

let person = Person(name: "hoge")
print(person.name)
// KVC
person.setValue("fuga", forKey: #keyPath(Person.name)) // "hoge"
person.value(forKey: #keyPath(Person.name))  // "fuga"
print(person.name)

person[keyPath: \Person.name] = "NG"
print(person.name) // "NG"

person[keyPath: \.name] = "OK"
print(person.name) // "OK"