Reputation: 1574
I was wondering, what are some of the most overarching protocols in Swift. I want to make an extension that applies to values that can be set. The purpose of this was to make it easier to write more one-lined code.
Note: for the time being, the "overarching" protocol that I am extending is Equatable
.
extension Equatable {
@discardableResult public func set(to variable: inout Self) -> Self {
variable = self
return self
}
}
Caveat: I would like to be able to use .set(to: )
for values that don't conform to Equatable
as well.
let ten = 10
var twenty = 0
(ten + 10).set(to: &twenty)
print(twenty)
// Prints "20"
This can be helpful when you need to set and return a value, now only one line of code is required to do so.
return value.set(to: &variable)
How do I make .set(to: )
more far reaching, without needing multiple instances of it?
Equatable
, CustomStringConvertible
, CVarArg
, there would be multiple suggestions of the same extensions for many values that conform to all 3 of these protocols.Bonus Question: is there a way in an extension to do something not dissimilar to extension Equatable where !(Element: CustomStringConvertible)
or extension Equatable where !(Element == Int)
(use the where
predicate for exclusion purposes)?
Upvotes: 1
Views: 187
Reputation: 299345
In most cases, I strong discourage this kind of code. "One-line" code is not generally a goal of Swift. Clear and concise is a goal, with clear winning when they're in conflict. Extending Any
this way (even if it were legal) is generally a very bad idea since set(to:)
could easily collide.
But in limited circumstances this may be useful within a single file or for a special use. In that case, it's easily implemented with operators.
infix operator -->
private func --> <T>(lhs: T, rhs: inout T) -> T {
rhs = lhs
return lhs
}
let ten = 10
var twenty = 0
(ten + 10) --> twenty
print(twenty)
// Prints "20"
The more natural way to do what you're describing is with protocols that you explicitly conform. For example:
protocol Settable {}
extension Settable {
@discardableResult public func set(to variable: inout Self) -> Self {
variable = self
return self
}
}
extension Int: Settable {}
extension String: Settable {}
extension Array: Settable {}
extension Optional: Settable {}
You can attach Settable
to any types that are useful for this purpose, and these extensions can be provided anywhere in the project (even in other modules). There is no way to attach a method to every possible type in Swift.
Upvotes: 3