Extentions for more than one protocol at once - swift

I want to write extensions for more than one protocol and found this posting which was very interesting, but I wasn't able to follow Matthew Seaman completely.
In this case I want to write my own extension BinaryNumber which I want to add to BinaryInteger and BinaryFloatingPoint. But when I try to add my protocol, Xcode shows the error message Extension of protocol 'BinaryInteger' (or 'BinaryFloatingPoint') cannot have an inheritance clause.
Here is my code:
protocol BinaryNumbers {} // my protocol
extension BinaryNumbers {
func foo() -> Void {
print("It works!")
}
}
// try to extend Swift protocols
extension BinaryInteger : BinaryNumbers {} // doesn't work
extension BinaryFloatingPoint : BinaryNumbers {} // doesn't work
//Updade
#sweeper suggested to extend Numeric, so I tried, but get an error.
extension Numeric {
func foo() -> Bool {
return self <= 127
// Referencing operator function '<=' on 'BinaryInteger' requires
// that 'Self' conform to 'BinaryInteger'
}
}
When I extend BinaryInteger and BinaryFloatingPoint one by one, it works.

In general, it is not possible to write a single extension on multiple protocols. This would require the compiler to figure out the set intersection of all the members in all those protocols (those are the members you have access to in the extensions), which the compiler cannot do.
To avoid code duplication, you would need to work out the members that you need - in your case init(integerLiteral:) and <=, put those in your own protocol, and make the concrete types you want the extension to apply to, conform to your own protocol:
// inheriting from Comparable and ExpressibleByIntegerLiteral gives you the members you need
protocol BinaryNumbers : Comparable & ExpressibleByIntegerLiteral {
}
extension BinaryNumbers {
func atMost127() -> Bool {
self <= 127
}
}
extension Int: BinaryNumbers {}
extension Int8: BinaryNumbers {}
extension Int16: BinaryNumbers {}
extension Int32: BinaryNumbers {}
extension Int64: BinaryNumbers {}
// ... plus the unsigned versions, if you need them
extension Float16: BinaryNumbers {}
extension Float32: BinaryNumbers {}
extension Float64: BinaryNumbers {}
extension Float80: BinaryNumbers {}
Now you might ask, why don't we just make an extension of Comparable & ExpressibleByIntegerLiteral then, as they provide all the members we are using? Well, because that's not a nominal type, and you can't write extensions on non-nominal types :(
However, you could write it in this way:
// now you don't need your own "BinaryNumbers"!
extension Comparable where Self: ExpressibleByIntegerLiteral {
func atMost127() -> Bool {
self <= 127
}
}
You are only able to do this because the two members you need all came from protocols. If for some reason you need a member that both BinaryFloatingPoint and BinaryInteger has, but isn't provided by any of the protocols they conform to, then you need to write your own protocol with those members, and manually conform everything to that protocol.

Related

swift protocol method when associated meets a constraint

I have a protocol with associated type.
I want the protocol to impose some method only if the associated type conforms to Equatable.
Something like this:
public protocol ListOfThings {
associatedtype ThingType
func append(_ thing: ThingType)
// This function makes sense only if ThingType is equatable
func remove(_ thing: ThingType) where ThingType: Equatable
}
I just can't find the right syntax for that.
I also tried with an extension, but the compiler (rightly) claims for the function body.
extension ListOfThings where ThingType: Equatable {
func remove(_ thing: ThingType)
}
To make #matt's comment concrete, this is in fact two protocols with different constraints. So give those different things different names:
public protocol ListOfThings {
associatedtype ThingType
func append(_ thing: ThingType)
}
// This requires that anything conforming to RemovableListOfThings
// also conform to ListOfThings, and that ThingType conform to Equatable,
// and that the type also implements `remove`.
public protocol RemovableListOfThings: ListOfThings
where ThingType: Equatable {
func remove(_ thing: ThingType)
}
What you're trying to do can't work since a type might be conformed to Equatable in another module. The compiler can't go back and revoke the conformance to ListOfThings just because the type is later conformed to Equatable (thus changing the requirements retroactively).

Requiring, for a protocol, that an instance variable conform to a protocol ; rather than have a specific type

As part of a custom Coder, I convert both Float and Double in the exact same way :
static func encode(_ value : Double) -> Data {
withUnsafeBytes(of: value.bitPattern.bigEndian) { Data($0) }
}
static func encode(_ value : Float) -> Data {
withUnsafeBytes(of: value.bitPattern.bigEndian) { Data($0) }
}
I thought that instead I could require that value would conform to a protocol, and since the FloatingPoint protocol does not guarantee the presence of bitPattern, I thought I would make my own :
protocol CompatibleFloatingPoint {
var bitPattern : FixedWidthInteger { get }
}
This, however, gives the following error :
Protocol 'FixedWidthInteger' can only be used as a generic constraint because it has Self or associated type requirements
However, I cannot replace FixedWidthInteger with a specific type, as Double.bitPattern is a UInt64 and Float.bitPattern is a UInt32
What is the proper syntax to require that bitPattern conform to the FixedWidthInteger protocol without forcing it to have a specific type ?
What you're looking for is an associated type. This means exactly what you've described (the required type conforms to a protocol rather than being the existential of that protocol):
protocol CompatibleFloatingPoint {
associatedtype BitPattern: FixedWidthInteger
var bitPattern : BitPattern { get }
}
extension Float: CompatibleFloatingPoint {}
extension Double: CompatibleFloatingPoint {}
For more details, see Associated Types in the Swift Programming Language.

What's the point of conforming to an empty protocol in Swift

I'm just working on a codebase where the most classes conform to an empty protocol. Is there any point of doing so? Actually conforming that protocol does nothing.
Edit as reaction to #vacawama's helpful comment : the protocol is only used once
import Foundation
protocol myUrlRequestConfig {}
extension myUrlRequest: myUrlRequestConfig {
public static func configGetAppConfig() -> URLRequest {
let request = ....
return request
}
}
An empty protocol can be useful if you want to create an easy way to add static functions or variables to several different classes. Of course, this only makes sense if the static functionality is the same for all classes conforming to the protocol.
Here is an example: I have a protocol sizeable. Every class that conforms to Sizeable is extended with the static variable stride and size.
protocol Sizeable { }
extension Sizeable {
static var size: Int {
return MemoryLayout<Self>.size
}
static var stride: Int {
return MemoryLayout<Self>.stride
}
}
class Foo: Sizeable {}
class Baa: Sizeable {}
Foo.size
Baa.size
Our app has three perfectly legitimate uses for an empty protocol:
The protocol has an extension with method definitions. The implementation in the extension is automatically injected into any type that adopts the protocol.
The protocol has other protocols that adopt it. This allows multiple protocols to be unified under a single head.
The protocol marks the adopter as wanting some other type to behave in a certain way. Code can always is whether an object is ThisEmptyProtocol and if it is, can behave differently than if it isn't.

Widespread Swift Protocol for Extensions

Widespread Protocol for Extensions
Swift 4.1, Xcode 9.3
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.
My Extension:
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.
Usage:
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)
Final Question
How do I make .set(to: ) more far reaching, without needing multiple instances of it?
For example, if I wrote the same extension for Equatable, CustomStringConvertible, CVarArg, there would be multiple suggestions of the same extensions for many values that conform to all 3 of these protocols.
If this is not possible, what is the best overarching protocol that I can use?
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)?
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.

Abstract Access to Bitwise Shifts in Swift

So a little while ago I was working on some code in Swift that would allow me to do some useful extra manipulation of integers as binary, including getting the highest and lowest bits that are actually set.
As an example, here's a basic property I added that is now broken:
extension IntegerType {
var hiBit:Self { return ~self.allZeroes << ((sizeof(Self) * 8) - 1) }
}
This won't compile now because IntegerType no longer conforms to BitwiseOperationsType so the tilde operator and allZeroes properties are no longer available to it. Likewise there doesn't appear to be any requirement anymore for structs implementing IntegerType or BitwiseOperationsType to have shift operators, they just seem to be defined by convention now, unless I've missed something. This means that I can't transplant my code to BitwiseOperationsType either, even though it seems like the more logical place for it to be.
So my question is; where do I implement my code at the highest level? I don't want to have to duplicate it for every specific integer type, which is why I was extending IntegerType to begin with.
Also as an aside, I originally implemented hiBit as a static property, but these no longer appear to be supported, which is weird as they clearly were, and the error message implies that they will be in future, suggesting they were pulled from the spec; but I'm not running the Xcode beta.
There is no protocol which defines the bit shift operators, so you have
to define your own:
protocol ShiftOperationsType : BitwiseOperationsType {
func <<(lhs: Self, rhs: Self) -> Self
func >>(lhs: Self, rhs: Self) -> Self
init(_ value : Int)
}
Unfortunately, you have to declare the conformance of the integer type
to that protocol explicitly for each type (at present there is no
simpler solution, compare What protocol should be adopted by a Type for a generic function to take any number type as an argument in Swift?).
extension Int : ShiftOperationsType {}
extension Int8 : ShiftOperationsType {}
extension Int16 : ShiftOperationsType {}
extension Int32: ShiftOperationsType {}
extension Int64: ShiftOperationsType {}
extension UInt : ShiftOperationsType {}
extension UInt8 : ShiftOperationsType {}
extension UInt16 : ShiftOperationsType {}
extension UInt32 : ShiftOperationsType {}
extension UInt64 : ShiftOperationsType {}
But then you can define hiBit as a generic static property:
extension ShiftOperationsType {
static var hiBit : Self {
return (~allZeros) << Self(sizeof(Self) * 8 - 1)
}
}
The init method in the protocol is necessary because sizeof()
returns an Int and has to be converted to Self.