Skip to content

Instantly share code, notes, and snippets.

@maximkrouk
Last active June 7, 2020 11:25
Show Gist options
  • Save maximkrouk/a65da65131a4a5fcb54e7cbbbd3960c6 to your computer and use it in GitHub Desktop.
Save maximkrouk/a65da65131a4a5fcb54e7cbbbd3960c6 to your computer and use it in GitHub Desktop.
Useful swift extension for optionals
@inlinable
func wrap<T>(_ value: T) -> T? { .some(value) }
extension Optional {
@inlinable
var isNotNil: Bool { !isNil }
@inlinable
var isNil: Bool {
switch self {
case .none: return true
case .some: return false
}
}
@inlinable
func `as`<T>(_ type: T.Type) -> T? { self as? T }
func or(_ value: @autoclosure () throws -> Wrapped) rethrows -> Wrapped {
switch self {
case let .some(value):
return value
case .none:
return try value()
}
}
func or(_ value: @autoclosure () throws -> Wrapped?) rethrows -> Wrapped? {
switch self {
case let .some(value):
return value
case .none:
return try value()
}
}
func unwrap() -> Result<Wrapped, Error> {
switch self {
case .some(let value):
return .success(value)
case .none:
return .failure(UnwrappingError(Wrapped.self))
}
}
@inlinable
static func update(_ value: inout Wrapped, using optional: Self) {
if let unwrapped = optional { value = unwrapped }
}
}
struct UnwrappingError<T>: Error {
let type: T.Type
let function: String
let file: String
let line: Int
init(
_ type: T.Type,
function: String = #function,
file: String = #file,
line: Int = #line
) {
self.type = type
self.function = function
self.file = file
self.line = line
}
var localizedDescription: String {
"Could not unwrap value of type \(type)."
}
var debugDescription: String {
localizedDescription
.appending("\n{")
.appending("\n function: \(function)")
.appending("\n file: \(file),")
.appending("\n line: \(line)")
.appending("\n}")
}
}
@maximkrouk
Copy link
Author

maximkrouk commented Mar 27, 2020

Usage

Optional

let string = Optional<String>.none

string.or("") // ""

switch string.unwrap() {
case .success(let value): print(value)
case .failure(let error): print(error.localizedDescription)
}

if string.isNotNil { print("There was a value" }

if string.isNil { print("Nothing here ☹️") }

let any: Any? = 2020
let year = any.as(Int.self).or(2019) // 2020

Back to index

@vmanot
Copy link

vmanot commented Apr 8, 2020

I think you should take a look at Swallow. Seems like we have a lot of common ideas!

@maximkrouk
Copy link
Author

maximkrouk commented May 30, 2020

Yep, there are a lot of great ideas for optionals and more, definitely worth having a look 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment