Last active
July 27, 2021 07:08
-
-
Save davidsteppenbeck/4c5e305cc85bd98f22291f1c6a07d799 to your computer and use it in GitHub Desktop.
An infix operator for collections that returns the wrapped value of the optional only if the collection is not empty.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
infix operator ??? | |
extension Optional where Wrapped: Collection { | |
/// Performs a nil-coalescing operation, returning the wrapped value of an `Optional` instance | |
/// only if the wrapped value is not empty, otherwise returns a default value. | |
/// | |
/// - Parameters: | |
/// - optional: An optional value. | |
/// - defaultValue: A value to use as a default. | |
static func ??? (optional: Self, defaultValue: @autoclosure () -> Wrapped) -> Wrapped { | |
if let wrappedValue = optional, !wrappedValue.isEmpty { | |
return wrappedValue | |
} else { | |
return defaultValue() | |
} | |
} | |
} |
defaultValue
should be an@autoclosure () -> Self
. If defaultValue is just a string literal, this isn’t a problem, but what if it’s an expensive function call? It should only be computed if needed, just like Optional’s??
operator works
Hey Emil 👋
I actually did try to do that initially, as it is done with ?? like you said, but it results in this error:
Member operator '???' of protocol 'Collection' must have at least one argument of type 'Self'
But I agree that it would be better using a closure. Any ideas?
Oh yeah, you'll have to put the extension on Optional where Wrapped: Collection
so the left hand side can be of type Self:
import Foundation
infix operator ???
extension Optional where Wrapped: Collection {
/// Performs a nil-coalescing operation, returning the wrapped value of an `Optional` instance
/// only if the wrapped value is not empty, otherwise returns a default value.
///
/// - Parameters:
/// - optional: An optional value.
/// - defaultValue: A value to use as a default.
static func ??? (optional: Self, defaultValue: @autoclosure () -> Wrapped) -> Wrapped {
if let wrappedValue = optional, !wrappedValue.isEmpty {
return wrappedValue
} else {
return defaultValue()
}
}
}
Great idea! I updated it, thanks 👍
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
defaultValue
should be an@autoclosure () -> Self
. If defaultValue is just a string literal, this isn’t a problem, but what if it’s an expensive function call? It should only be computed if needed, just like Optional’s??
operator works