LoginSignup
5
2

More than 5 years have passed since last update.

SwiftのOptionalをScala風に拡張するExtensionを書いてみた

Last updated at Posted at 2016-03-11

こんにちは!

普段iOSではSwiftを、Androidやサーバー側の開発ではScalaを利用して開発をしています。

どちらも微妙に似ていて、けれど、やはり違っているので、

たまにSwiftならこう書けるのに、とか、Scalaならこう書けるのに、と思うことがあります。

なので、SwiftのOptionalをScalaっぽく扱えるように拡張してみました。

ScalikeOptional.swift

ワンライナー縛りで書いています。

GitHubにあげました
https://github.com/iTerasaka/ScalikeOptional.swift


// MARK: - ScalikeOptional.swift

extension Optional {

    static func empty() -> Wrapped? {
        return Optional<Wrapped>.None
    }

    public var get: Wrapped {
        return self!
    }

    public var isEmpty: Bool {
        return self.map { _ in false } ?? true
    }

    public var isDefined: Bool {
        return !self.isEmpty
    }

    public func getOrElse(p: Wrapped) -> Wrapped {
        return self ?? p
    }

    public func orElse(p: Wrapped) -> Wrapped? {
        return Optional(self ?? p)
    }

    public func forEach(@noescape f: Wrapped -> Void) -> Void {
        if let some = self { f(some) }
    }

    public func forAll(@noescape f: Wrapped -> Bool) -> Bool {
        return self.map(f) ?? true
    }

    public func fold<A>(ifEmpty: A, @noescape _ f: Wrapped -> A) -> A {
        return self.map(f) ?? ifEmpty
    }

    public func exists(@noescape p: Wrapped -> Bool) -> Bool {
        return self.map(f) ?? false
    }

    public func collect<A, B>(@noescape f: A -> B) -> B? {
        return (self as? A).map(f) ?? nil
    }

    public func filter(@noescape p: Wrapped -> Bool) -> Wrapped? {
        return self.exists(p) ? self : nil
    }
}

試してみる

// MARK: - prepare

var str: String? = "hoge"
var strOpt: String? = nil

// MARK: - property

str.get // "hoge"
strOpt.get // throw Error

str.isEmpty // false
strOpt.isEmpty // true

str.isDefined // true
strOpt.isDefined // false

strOpt.getOrElse("空です") // "hoge"
strOpt.getOrElse("空です") // "空です"

strOpt.orElse("空です") // Optional("hoge")
strOpt.orElse("空です") // Optional("空です")

// MARK: - forEach

str.forEach { print("\($0)がはいっています") } // print(hogeがはいっています)
strOpt.forEach { print("\($0)がはいっています") } // なにもしない

// MARK: - forAll

str.forAll { $0 == "h" } // false
str.forAll { $0 == "hoge" } // true
strOpt.forAll { $0 == "hoge" } // true

// MARK: - exists

str.exists { $0 == "h" } // false
str.exists { $0 == "hoge" } // true

// MARK: - fold

str.fold(false) { return $0 == "hoge" } // true
str.fold(false) { return $0 == "h" } // false

strOpt.fold(false) { return $0 == "hoge" } // false
strOpt.fold(false) { return $0 == "h" } // false

// MARK: - collect

str.collect { (a:String) in return a + "がはいっています" } // hogeがはいっています
strOpt.collect { (a:String) in return a + "1" } // nil
str.collect { (a:Int) in return a + 1 } // nil
strOpt.collect { (a:String) in return a + "1" } // nil

// MARK: - filter

str.filter { $0 == "hoge" } // Optional(hoge) 
str.filter { $0 == "aaa" } // nil


結論

Optional便利ですねー

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2