Lavieleaf

おもったことをなんでも書くことろ

try! Swift 2018 裏 Swfit Tour メモ


裏Swift Tourの内容がおもしろかったのでコードとともにメモしておきます。

代入

代入すると返り値があるとは知りませんでした。 .map などの高階関数の使い方もなるほどなと思いました。

var myVariable = 42
let r = (myVariable = 50)
type(of: r) // => (): 空のTuple

struct Obj {
    var myVariable = 50
}
var obj: Obj? = Obj()
obj?.myVariable = 50
type(of: (obj?.myVariable = 50)) // => Optional<()>: Optional の空のTuple

(obj?.myVariable = 50).map { /* 代入が上手くいったときだけ処理する */ }

Optional Chaining

precedencegroupなるものがあるんですね。

/// オペレータを 💩 にしようと思ったけどエラー↓できなかった
/// error: '💩' is considered to be an identifier, not an operator

precedencegroup FoldedIntoOptionalChaining {
    assignment: true
}
infix operator : FoldedIntoOptionalChaining
func  (left: Int, right: Int) -> Int {
    return left + right
}

obj?.myVariable  50 // ==> 100
obj = nil
obj?.myVariable  50 // ==> nil

クロージャ

struct SomeClass {
    /// var v: Int!

    /// これは nil でもない、Optional型でもない
    lazy var v: Int = { preconditionFailure("Variable '\(#function)' used before being innitialized") }()

    /// これらはビルドが通る
    let a: Int = { preconditionFailure() }()
    let b: Void = { fatalError() }()
    let c: Never = { while(true) {} }()
}

たまにどうしても ! つけたくないときがあるのでそのときは使ってみようと思う。

inout

func f(_ arg: inout String) {
    arg = "🐣"
    arg = "🐓"
}

var testString = "🥚" {
    didSet {
        print("changed: \(testString)")
    }
}
f(&testString) /// => "🐓" (didSetは一度しか呼ばれない)

didSet がある場合は、 inout にコピーが渡されるため最後の値がコピー元に入るので一度しか呼ばれないらしい。 didSet がない場合は、コピーではなく参照を渡しているので arg = "🐣" の時点で testString に "🐣" が代入される。

Swiftは知らないことばかりだとと痛感させられた。。