Abstract Access to Bitwise Shifts in Swift - 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.

Related

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.

Extentions for more than one protocol at once

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.

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.

How can I convert between related types through a common initializer?

I'm trying to build up a family of types that can be converted to each other. For example, Float and Double can be converted to each other through their initializers. I'd like to not have to create an exhaustive list of initializers showing that each type can convert to every other type.
I tried to do something like this in a Playground, but it crashes:
protocol FloatConvertible {
init(_ x:FloatConvertible)
}
extension FloatConvertible {
init(_ x:FloatConvertible){self.init(Self(x))}
}
extension Float:FloatConvertible {}
extension Double:FloatConvertible {}
func transmute<T:FloatConvertible, U:FloatConvertible>
(a:T, b:U) -> T {
return T(b)
}
transmute(Float(3.1), b: Double(2.6))
My eventual goal isn't just to do the conversion, but to multiply a by b like so:
func *<T:FloatConvertible, U:FloatConvertible> (a:T, b:U) -> T{
return a * T(b)
}
So that I can express the multiply.
Is there a way to do this? I think part of the problem is winding up with a structure that looks like Double(Double(Double(Double(...))), but I don't think I can put a constraint that ensures T != U.
The problem is that in your init(_ x:FloatConvertible), Swift cannot infer what the concrete type of x is. It just knows that it's a FloatConvertible. Therefore when you try to do Self(x), while it can infer the concrete type of Self, it doesn't know which initialiser you want to call, meaning that it will default to your init(_ x:FloatConvertible) initialiser, thus creating an infinite loop.
If you give your custom initialiser an argument name, you'll see that Swift complains that it can't find the correct initialiser:
protocol FloatConvertible {
init(c x:FloatConvertible)
}
extension FloatConvertible {
init(c x:FloatConvertible) {
// error: missing argument name 'c:' in call
// (i.e it can't find the concrete type's initialiser)
self.init(Self(x))
}
}
A potential solution therefore is to resolve this at runtime by switching over the concrete types that x could be. However this isn't nearly as good as resolving this statically, as you can benefit from increased safety and in some cases increased performance.
In order to do this statically, you could add a generic _asOther 'shadow' function to your protocol that can convert a given floating point type to another, as well as adding the concrete type's initialisers to your protocol requirement.
This will save you from having to list out all the possible combinations of conversions – you can now just invoke _asOther from your initialiser.
protocol FloatConvertible {
init(_ other:Float)
init(_ other:Double)
init(_ other:CGFloat)
init(fromOther x:FloatConvertible)
func _asOther<T:FloatConvertible>() -> T
}
extension FloatConvertible {
init(fromOther x:FloatConvertible) {self = x._asOther()}
}
// note that we have to implement these for each extension,
// so that Swift uses the concrete types of self, preventing an infinite loop
extension Float : FloatConvertible {
func _asOther<T:FloatConvertible>() -> T {return T(self)}
}
extension Double : FloatConvertible {
func _asOther<T:FloatConvertible>() -> T {return T(self)}
}
extension CGFloat : FloatConvertible {
func _asOther<T:FloatConvertible>() -> T {return T(self)}
// note that CGFloat doesn't implement its own initialiser for this,
// so we have to implement it ourselves
init(_ other:CGFloat) {self = other}
}
func transmute<T:FloatConvertible, U:FloatConvertible>(value: T, to: U.Type) -> U {
return U(fromOther: value)
}
let f = transmute(value: CGFloat(2.6), to: Float.self)
print(type(of: f), f) // prints: Double 2.59999990463257
In the initialiser, _asOther will be called on the input value, with the type of self being inferred for the generic parameter T (in this context self is guaranteed to be a concrete type). The _asOther function will then get called on x, which will return the value as the given destination type.
Note that you don't have to use the fromOther: argument label for your custom initialiser – this will still work without any label. Although I would strongly advocate for using it to catch any problems with your code at compile time (Swift would accept code that would cause infinite loops at runtime otherwise).
Also as a side note, you should maybe re-think your design for how you want your * overload to work. It would make more sense to be returning the more precise type that you input into it (i.e Float * Double = Double) – otherwise you're just needlessly losing precision.

Define a Swift protocol which requires a specific type of sequence

Suppose for example we're talking about elements of type Int (but the question still applies to any type)
I have some functionality which needs to loop over a sequence of Ints. But I don't care if behind the scenes this sequence is implemented as an Array, or a Set or any other exotic kind of structure, the only requirement is that we can loop over them.
Swift standard library defines the protocol SequenceType as "A type that can be iterated with a for...in loop". So my instinct is to define a protocol like this:
protocol HasSequenceOfInts {
var seq : SequenceType<Int> { get }
}
But this doesn't work. SequenceType is not a generic type which can be specialized, it's a protocol. Any particular SequenceType does have a specific type of element, but it's only available as an associated type: SequenceType.Generator.Element
So the question is:
How can we define a protocol which requires a specific type of sequence?
Here's some other things I've tried and why they aren't right:
Fail 1
protocol HasSequenceOfInts {
var seq : SequenceType { get }
}
Protocol 'SequenceType' can only be used as a generic constraint
because it has Self or associated type requirements
Fail 2
protocol HasSequenceOfInts {
var seq : AnySequence<Int> { get }
}
class ArrayOfInts : HasSequenceOfInts {
var seq : [Int] = [0,1,2]
}
I thought this one would work, but when I tried a concrete implementation using an Array we get
Type 'ArrayOfInts' does not conform to protocol 'HasSequenceOfInts'
This is because Array is not AnySequence (to my surprise... my expectation was that AnySequence would match any sequence of Ints)
Fail 3
protocol HasSequenceOfInts {
typealias S : SequenceType
var seq : S { get }
}
Compiles, but there's no obligation that the elements of the sequence seq have type Int
Fail 4
protocol HasSequenceOfInts {
var seq : SequenceType where S.Generator.Element == Int
}
Can't use a where clause there
So now I'm totally out of ideas. I can easily just make my protocol require an Array of Int, but then I'm restricting the implementation for no good reason, and that feels very un-swift.
Update Success
See answer from #rob-napier which explains things very well. My Fail 2 was pretty close. Using AnySequence can work, but in your conforming class you need to make sure you convert from whatever kind of sequence you're using to AnySequence. For example:
protocol HasSequenceOfInts {
var seq : AnySequence<Int> { get }
}
class ArrayOfInts : HasSequenceOfInts {
var _seq : [Int] = [0,1,2]
var seq : AnySequence<Int> {
get {
return AnySequence(self._seq)
}
}
}
There are two sides to this problem:
Accepting an arbitrary sequence of ints
Returning or storing an arbitrary sequence of ints
In the first case, the answer is to use generics. For example:
func iterateOverInts<SeqInt: SequenceType where SeqInt.Generator.Element == Int>(xs: SeqInt) {
for x in xs {
print(x)
}
}
In the second case, you need a type-eraser. A type-eraser is a wrapper that hides the actual type of some underlying implementation and presents only the interface. Swift has several of them in stdlib, mostly prefixed with the word Any. In this case you want AnySequence.
func doubles(xs: [Int]) -> AnySequence<Int> {
return AnySequence( xs.lazy.map { $0 * 2 } )
}
For more on AnySequence and type-erasers in general, see A Little Respect for AnySequence.
If you need it in protocol form (usually you don't; you just need to use a generic as in iterateOverInts), the type eraser is also the tool there:
protocol HasSequenceOfInts {
var seq : AnySequence<Int> { get }
}
But seq must return AnySequence<Int>. It can't return [Int].
There is one more layer deeper you can take this, but sometimes it creates more trouble than it solves. You could define:
protocol HasSequenceOfInts {
typealias SeqInt : IntegerType
var seq: SeqInt { get }
}
But now HasSequenceOfInts has a typealias with all the limitations that implies. SeqInt could be any kind of IntegerType (not just Int), so looks just like a constrained SequenceType, and will generally need its own type eraser. So occasionally this technique is useful, but in your specific case it just gets you basically back where you started. You can't constrain SeqInt to Int here. It has to be to a protocol (of course you could invent a protocol and make Int the only conforming type, but that doesn't change much).
BTW, regarding type-erasers, as you can probably see they're very mechanical. They're just a box that forwards to something else. That suggests that in the future the compiler will be able to auto-generate these type-erasers for us. The compiler has fixed other boxing problems for us over time. For instance, you used to have to create a Box class to hold enums that had generic associated values. Now that's done semi-automatically with indirect. We could imagine a similar mechanism being added to automatically create AnySequence when it's required by the compiler. So I don't think this is a deep "Swift's design doesn't allow it." I think it's just "the Swift compiler doesn't handle it yet."
(Tested and working in Swift 4, which introduces the associatedtype constraints needed for this)
Declare your original protocol that things will conform to:
protocol HasSequenceOfInts {
associatedType IntSequence : Sequence where IntSequence.Element == Int
var seq : IntSequence { get }
}
Now, you can just write
class ArrayOfInts : HasSequenceOfInts {
var seq : [Int] = [0,1,2]
}
like you always wanted.
However, if you try to make an array of type [HasSequenceOfInts], or assign it to a variable (or basically do anything with it), you'll get an error that says
Protocol 'HasSequenceOfInts' can only be used as a generic constraint because it has Self or associated type requirements
Now comes the fun part.
We will create another protocol HasSequenceOfInts_ (feel free to choose a more descriptive name) which will not have associated type requirements, and will automatically be conformed to by HasSequenceOfInts:
protocol HasSequenceOfInts: HasSequenceOfInts_ {
associatedType IntSequence : Sequence where IntSequence.Element == Int
var seq : IntSequence { get }
}
protocol HasSequenceOfInts_ {
var seq : AnySequence<Int> { get }
}
extension HasSequenceOfInts_ where Self : HasSequenceOfInts {
var seq_ : AnySequence<Int> {
return AnySequence(seq)
}
}
Note that you never need to need to explicitly conform to HasSequenceOfInts_ , because HasSequenceOfInts already conforms to it, and you get a full implementation for free from the extension.
Now, if you need to make an array or assign an instance of something conforming to this protocol to a variable, use HasSequenceOfInts_ as the type instead of HasSequenceOfInts, and access the seq_ property (note: since function overloading is allowed, if you made a function seq() instead of an instance variable, you could give it the same name and it would work):
let a: HasSequenceOfInts_ = ArrayOfInts()
a.seq_
This needs a bit more setup than the accepted answer, but means you don't have to remember to wrap your return value in AnySequence(...) in every type where you implement the protocol.
I believe you need to drop the requirement for it to only be Int's and work around it with generics:
protocol HasSequence {
typealias S : SequenceType
var seq : S { get }
}
struct A : HasSequence {
var seq = [1, 2, 3]
}
struct B : HasSequence {
var seq : Set<String> = ["a", "b", "c"]
}
func printSum<T : HasSequence where T.S.Generator.Element == Int>(t : T) {
print(t.seq.reduce(0, combine: +))
}
printSum(A())
printSum(B()) // Error: B.S.Generator.Element != Int
In Swift's current state, you can't do exactly what you want, maybe in the future though.
it is very specific example on request of Daniel Howard
1) type conforming to SequenceType protocol could be almost any sequence, even though Array or Set are both conforming to SequenceType protocol, most of their functionality comes from inheritance on CollectionType (which conforms to SequenceType)
Daniel, try this simple example in your Playground
import Foundation
public struct RandomIntGenerator: GeneratorType, SequenceType {
public func next() -> Int? {
return random()
}
public func nextValue() -> Int {
return next()!
}
public func generate() -> RandomIntGenerator {
return self
}
}
let rs = RandomIntGenerator()
for r in rs {
print(r)
}
As you can see, it conforms to SequenceType protocol and produce infinite stream of Int numbers. Before you will try to implement something, you have to answer yourself few questions
can i reuse some functionality, which is available 'for free' in standard Swift library?
am i trying to mimic some functionality which is not supported by Swift? Swift is not C++, Swift is not ObjectiveC ... and lot of constructions we used to use before Swift has no equivalent in Swift.
Define your question in such way that we can understand you requirements
are you looking for something like this?
protocol P {
typealias Type: SequenceType
var value: Type { get set }
}
extension P {
func foo() {
for v in value {
dump(v)
}
}
}
struct S<T: CollectionType>: P {
typealias Type = T
var value: Type
}
var s = S(value: [Int]())
s.value.append(1)
s.value.append(2)
s.foo()
/*
- 1
- 2
*/
let set: Set<String> = ["alfa", "beta", "gama"]
let s2 = S(value: set)
s2.foo()
/*
- beta
- alfa
- gama
*/
// !!!! WARNING !!!
// this is NOT possible
s = s2
// error: cannot assign value of type 'S<Set<String>>' to type 'S<[Int]>' (aka 'S<Array<Int>>')