kentana20 技忘録

技術ネタを中心に、セミナー、勉強会、書籍、会社での出来事を綴っていきます。不定期更新。

詳解Swift#4(chapter7 演算子)

昨日に続いて、詳解Swiftの写経を続ける。

詳解 Swift 改訂版

詳解 Swift 改訂版

chapter7 演算子

演算子だけのchapterがあるってすごい。内容はさらっと。

Swift演算子

目についた部分だけメモ。

  • シフト演算
  • 四則演算
  • ビット操作

などが優先。

  • 比較
  • 条件判断

などは優先度低。

// オーバーフロー演算子
z - 1
//z - 2 <- error
z &- 2

// 剰余演算子
11 % 2.5
11.0 % 2.5

var x: Int = 10
x = 5
x % 2
x // 5
x %= 2 // 複合代入演算子
x // 1

// ビット演算子
func odd(i:Int) -> Bool { print(i); return i&1 == 1 }

var b = true
var c1 = b || odd(1)  // oddは実行されない
var c2 = !b && odd(3) // oddは実行されない

&& , || は短絡評価。

演算子の定義

Swiftでは演算子を独自に定義したり、既存の定義をオーバーライドすることもできる(できないものもある)。

infix operator 演算子 {
    precedence 数字(優先度)
    associativity 規則(left|right|none)
}

func 演算子(左項: 型, 右項: 型) {
    return 戻り値
}
prefix operator 演算子 {}
postfix operator 演算子 {}

でそれぞれ定義できる。

  • サンプル
// ~ を演算子として定義した例
infix operator 〜 {      // 二項(中置)演算子として宣言
    precedence 20        // 他の演算子より低い優先度
    associativity none   // 結合規則は「なし」
}
func 〜 (n:Int, w:Int) -> String {
    var str = String(n)  // Stringのイニシャライザで、整数を文字列にする
    let pad = w - str.characters.count  // 左に詰める空白の個数
    if pad > 0 {
        str = String(count:pad,
                     repeatedValue:Character(" ")) + str
    }
    return str
}

タプル、列挙型などのパターン、整数と区間についてのマッチングを行う演算子~= で利用できる。また、~= 演算子を独自定義することで必要に応じた場合分けができる。が、グローバルに影響を与えるので、使うのはあまり、、、、的な記述が最後にあった。

enum Rank : Int {
    case Ace = 1, Two, Three, Four, Five, Six, Seven,
    Eight, Nine, Ten, Jack, Queen, King
}

// 実体型の値と等しい時もマッチしたものとする
func ~= (p:Int, r:Rank) -> Bool {
    return p == r.rawValue
}

let hand:[Rank] = [ .Queen, .Ace, .Ten, .Six, .King, .Jack ]
for card in hand {
    switch card {
    case 1: print("Ace")
    case 13: print("King")
    case .Queen: print("Queen")
    default: print(".")
    }
}

実体型の値もマッチするので、 "Ace", "King" も出力される。

所感・雑感

演算子

  • 独自定義
    • JSの既存のprototypeにメソッドを生やすみたいに、グローバルに影響がでるので使うの慎重になりそう
    • 業務的によく利用するもの(ex. 業務時間とか、金額の計算とか)は独自演算子を作って限定的に使うのがよいかもしれない

明日も続ける。