こんにちは!寺坂です。
普段iOSではSwiftを、Androidやサーバー側の開発ではScalaを利用して開発をしています。
どちらも微妙に似ていて、けれど、やはり違っているので、
たまにSwiftならこう書けるのに、とかScalaならこう書けるのに、と思うことがあります。
なので、SwiftのOptionalをScalaっぽく扱えるように拡張してみました。
ScalikeOptional.swift
ワンライナー縛りで書いています。
GitHubにあげました
GitHub - 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 f: 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便利ですねー
元記事はこちらです。 SwiftのOptionalをScala風に拡張するExtensionを書いてみた - Qiita