Extending Generic Integer Types in Swift - swift

So I'm trying to extend Swift's integer types with a few convenient functions that I use a lot, however I'm not clear on which protocols I should be extending.
As an example, let's say I want to implement a function for clamping a value (if it's less than a minimum set it to that, otherwise if it's greater than a maximum then set it to that instead). My first thought was to do something like this:
extension Int {
func clamp(minimum:Int, maximum:Int) {
if self < minimum { return minimum }
if self > maximum { return maximum }
return self
}
}
Bit of a simplistic example, but it illustrates the problem; if I want to now call this for a UInt then naturally I can't, so I have to add an equivalent to UInt, but that won't work for a UInt16 and so-on.
I thought that I could perhaps extend something higher up the chain, and use generics instead, however protocols such as IntegerType can't seem to be extended.
So, is there somewhere more appropriate that I could put my extension(s)?

For Swift 2, see Andriy Gordiychuk's answer, which will be correct then. If you require Swift 1, then this cannot be done with extensions, and must be done with free functions. This is why there are so many free functions in stdlib that became extensions in Swift 2.
For Swift 1, what you have to do is:
func clamp<T:Comparable>(value: T, #minimum:T, #maximum:T) -> T {
if value < minimum { return minimum }
if value > maximum { return maximum }
return value
}
If you prefer modifying the value (as Andriy's example does), you can do it this way:
func clamp<T:Comparable>(inout value: T, #minimum:T, #maximum:T) {
if value < minimum { value = minimum }
else if value > maximum { value = maximum }
}
Otherwise you have to write an extension on every type. It's the only other answer in Swift 1. Swift 2 is much better.

While Swift 2.0 is still in beta I suggest you to add extensions like you illustrated. You will have to copy-paste the same code for Int, Int64 etc, but there is no other way to do what you want at the moment.
Once Swift 2.0 is out you will be able to do this
extension IntegerType {
mutating func clamp(minimum:Self, maximum:Self) {
if self < minimum { self = minimum }
if self > maximum { self = maximum }
}
}
If you can wait with the release of your app until some time in September then I encourage you to start using Swift 2.0 right now.
Update
With Swift 2.0 you can also add extension to Comparable protocol which will ensure that clamp() is available for other types such as Double, Float, etc
extension Comparable {
mutating func clamp(minimum:Self, maximum:Self) {
if self < minimum { self = minimum }
if self > maximum { self = maximum }
}
}

By way of example, here is an integer implementation of clamped that also applies generically to anything that can use it:
extension Comparable
{
func clamped(from lowerBound: Self, to upperBound: Self) -> Self {
return min(max(self, lowerBound), upperBound)
}
func clamped(to range: ClosedRange<Self>) -> Self {
return min(max(self, range.lowerBound), range.upperBound)
}
}
extension Strideable where Self.Stride: SignedInteger
{
func clamped(to range: CountableClosedRange<Self>) -> Self {
return min(max(self, range.lowerBound), range.upperBound)
}
}
And the test cases:
7.clamped(from: 3, to: 6) // 6
7.clamped(to: 3 ... 6) // 6
7.clamped(to: 3 ... 7) // 7
7.clamped(to: 3 ... 8) // 7
7.0.clamped(to: 3.0 ... 6.0) // 6
7.0.clamped(to: 3.0 ... 7.0) // 7
7.0.clamped(to: 3.0 ... 8.0) // 7

extension Comparable {
func clamp(var minimum: Self, var _ maximum: Self) -> Self {
if maximum < minimum { swap(&maximum, &minimum) }
if self < minimum { return minimum }
if self > maximum { return maximum }
return self
}
}

You are on the right track. In fact you are talking about Protocol Oriented Programming.
Protocol extensions: Swift is very focused on protocol-oriented
development — there’s even a session on the topic at WWDC 2015. Swift
2.0 adds protocol extensions, and the standard library itself uses them extensively. Where you used to use global functions, Swift 2.0
now adds methods to common types so functions chain naturally, and
your code is much more readable.
https://developer.apple.com/swift/blog/?id=29
In fact a big feature of Swift 2.0 is that it allows you to add methods to protocols so you can add clamp to IntegerType.
The video explains very well the topic of Protocol Oriented Programming: https://developer.apple.com/videos/wwdc/2015/?id=408
You just need to upgrade to Swift 2.0.

Related

Performance of swift extensions on primitive types

I am wondering if there would be any performance difference between the following in swift:
let x = 42.42
print(floor(x))
and
let x = 42.42
extension Double {
func myFloor() -> Double {
return floor(self)
}
}
print(x.myFloor())
The compiler inlines the code in the second case and produces the same machine code. You can see for yourself, here.

How to create a generator in Swift?

Can I create a generator in Swift?
With iterator, I need store intermediate results, for example:
struct Countdown: IteratorProtocol, Sequence {
private var value = 0
init(start: Int) {
self.value = start
}
mutating func next() -> Int? {
let nextNumber = value - 1
if nextNumber < 0 {
return nil
}
value -= 1
return nextNumber
}
}
for i in Countdown(start: 3) {
print(i)
} // print 1 2 3
In this example, I need store the value.
In my situation, I want to use generator instead of iterator, because I don't want store the intermediate results of my sequence in each next.
Understanding how generators work (and why they are less important in swift) is at first difficult coming from Python.
Up to Swift v2.1 there was a protocol called GeneratorType. This was renamed to IteratorProtocol in Swift v3.0+. You can conform to this protocol to make your own objects that do just-in-time computations similar to what can be done in Python.
More information can be found in the Apple Documentation: IteratorProtocol
A simple example from IteratorProtocol page:
struct CountdownIterator: IteratorProtocol {
let countdown: Countdown
var times = 0
init(_ countdown: Countdown) {
self.countdown = countdown
}
mutating func next() -> Int? {
let nextNumber = countdown.start - times
guard nextNumber > 0
else { return nil }
times += 1
return nextNumber
}
}
let threeTwoOne = Countdown(start: 3)
for count in threeTwoOne {
print("\(count)...")
}
// Prints "3..."
// Prints "2..."
// Prints "1..."
However, you need to think about why you are using a generator:
Swift automatically does something "called copy on write." This means that many of the cases that use a Python generator to avoid the large copying cost of collections of objects (arrays, lists, dictionaries, etc) are unnecessary in Swift. You get this for free by using one of the types that use copy on write.
Which value types in Swift supports copy-on-write?
It is also possible to use a wrapper to force almost any object to be copy on write, even if it is not part of a collection:
How can I make a container with copy-on-write semantics?
The optimizations in swift usually mean that you do not not have to write generators. If you really do need to (usually because of data heavy, scientific calculations) it is possible as above.
Based on the code you provided and the little bit knowledge of generators that I do have, you can do something like
struct Countdown {
private var _start = 0
private var _value = 0
init(value: Int) {
_value = value
}
mutating func getNext() -> Int? {
let current = _start
_start += 1
if current <= _value {
return current
} else {
return nil
}
}
}
and then wherever you want to use it, you can do something like
var counter = Countdown(value: 5)
while let value = counter.getNext() {
print(value)
}
Walter provides a lot of good information, and generally you shouldn't be doing this in Swift, but even if you wanted an Iterator, the right way to do it is with composition, not by building your own. Swift has a lot of existing sequences that can be composed to create what you want without maintaining your own state. So in your example, you'd differ to a range's iterator:
struct Countdown: Sequence {
private var value = 0
init(start: Int) {
self.value = start
}
func makeIterator() -> AnyIterator<Int> {
return AnyIterator((0..<value).reversed().makeIterator())
}
}
for i in Countdown(start: 3) {
print(i)
} // print 1 2 3
Something has to keep the state; that's the nature of these kinds of functions (even in a world with coroutines). It's fine not to maintain it directly; just delegate to a more primitive type. Swift has a couple of dozen built-in Iterators you can use to build most things you likely need, and any iterator can be lifted to an AnyIterator to hide the implementation details. If you have something custom enough that it really requires a next(), then yes, storing the state is your problem. Something has to do it. But I've found this all to be extremely rare, and often suggests over-design when it comes up.
I have a solution similar to above, but with a slightly more "yield-y" feeling to it.
struct Countdown
{
static func generator(withStart: Int) -> () -> Int?
{
var start = withStart + 1
return {
start = start - 1
return start > 0 ? start : nil
}
}
}
let countdown = Countdown.generator(withStart: 5)
while let i = countdown()
{
print ("\(i)")
}

Elegant `bounded` methodology in Swift

I'm looking for a more elegant way to create bounded limiters for numbers, primarily to be used in setters. There are plenty of techniques for determining whether a value falls within bounds, but I don't see any native functions for forcing an incoming value to conform to those bounds.
The accepted answer here comes close but I want to cap the values rather than merely enforce them.
Here's what I have so far. I'm not sure about the Int extension. And I'd prefer to collapse the if-else into a single elegant line of code, if possible. Ideally I'd like to shorten the actual implementation in the struct, as well.
extension Int {
func bounded(_ min: Int, _ max: Int) -> Int {
if self < min {
return min
} else if self > max {
return max
} else {
return self
}
}
}
print(5.bounded(4, 6)) // 5
print(5.bounded(1, 3)) // 3
print(5.bounded(6, 9)) // 6
// Used in a sentence
struct Animal {
var _legs: Int = 4
var legs: Int {
get {
return _legs
}
set {
_legs = newValue.bounded(1, 4)
}
}
}
var dog = Animal()
print(dog.legs) // 4
dog.legs = 3
print(dog.legs) // 3
dog.legs = 5
print(dog.legs) // 4
dog.legs = 0
print(dog.legs) // 1
This is Apple's own approach, taken from this sample code:
func clamp<T: Comparable>(value: T, minimum: T, maximum: T) -> T {
return min(max(value, minimum), maximum)
}
I would generalize this extension to any Comparable, so that more types can benefit from it. Also, I would change the parameter to be a ClosedRange<Self> rather than two separate Self parameters, because that's the more common way of handling ranges in Swift. That'll come in especially handy when dealing with array indices.
extension Comparable {
func clamped(to r: ClosedRange<Self>) -> Self {
let min = r.lowerBound, max = r.upperBound
return self < min ? min : (max < self ? max : self)
}
}
// Usage examples:
10.clamped(to: 0...5) // => 5
"a".clamped(to: "x"..."z") // => "x"
-1.clamped(to: 0...1) // => 0
A very clean alternative to your if-else statements, keeping the readability would be:
extension Comparable{
func clamp(_ min: Self,_ max: Self) -> Self{
return min...max~=self ? self : (max < self ? max : min)
}
}
I think this is a good alternative to using a range as parameter, because, in my opinion, it is annoying to write 6.clamp((4...5)) each time insted of 6.clamp(4,5).
When it comes to your struct, I think you should not use this clamp extension at all, because, say, 100 does not mean 4... I cannot see the reason for doing this, but it's up to you.

Failing to implement Protocol Extension for conforming type

(feel free to retitle question as appropriate)
I'm working with a lot of BLE data, and for debugging purposes, I've found it easy to extend UInt8 with a HEX computed variable:
extension UInt8 {
var HEX:String {
return String(format: "%02X", self)
}
}
// 190.HEX --> "BE"
I found myself wanting a lowercase variant. And then I wanted it for UInt32 and UInt16 as well. Since the only thing that changes is the number of digits to print, I thought I could do this with a protocol of sorts (at least for education purposes).
protocol HexPrintable {
var hexDigitCount:Int { get }
}
extension UInt8:HexPrintable {
var hexDigitCount:Int {
return 2
}
}
extension UInt16:HexPrintable {
var hexDigitCount:Int {
return 4
}
}
extension UInt32:HexPrintable {
var hexDigitCount:Int {
return 8
}
}
Then comes the part where I want to take advantage of this and provide default implementations of the HEX and hex methods:
extension HexPrintable {
var HEX:String {
return String(format: "%0\(self.hexDigitCount)X", self)
}
var hex:String {
return String(format: "%0\(self.hexDigitCount)x", self)
}
}
I get a compiler error Argument type 'Self' does not conform to expected type 'CVarArgType'.
I think I understand this. It's saying that as a protocol, it can't guarantee that adopting types will be of a type (CVarArgType) that could be used in the String initializer like that. So I thought I could use a where clause for the first time. I modified my protocol extension to look like:
extension HexPrintable where Self == CVarArgType { ...
Which leads to a Same-type requirement makes generic parameter 'Self' non-generic. At which point my amateur type theorist understanding overflowed. What is the magic to make my two extension methods on different UInt sizes work?
The correct syntax would be
extension HexPrintable where Self : CVarArgType { ... }
Alternatively, make your HexPrintable protocol inherit from CVarArgType:
protocol HexPrintable : CVarArgType {
var hexDigitCount:Int { get }
}
Note that you can implement the same functionality
with a single extension on IntegerType, using sizeofValue()
to determine the output width:
extension IntegerType where Self : CVarArgType {
var HEX : String {
let size = sizeofValue(self)
return String(format: "%0\(2*size)X", self)
}
}
But there is another problem: The %X format expects a Int32 argument
(corresponding to the C int type). Both your and my above code will
not produce correct results for values exceeding the range of a 32-bit
integer.
Various possible solutions to that problem are given e.g. in
How to create a generic integer-to-hex function for all Integer types? (and I just added another
one).

Swift 1.2 redeclares Objective-C method

I just updated from swift 1.1 to swift 1.2 and get compiler Error:
Method 'setVacation' redeclares Objective-C method 'setVacation:'
Here some code:
var vacation : Vacation?
func setVacation(_vacation : Vacation)
{...}
But I need call setVacation
Is any suggestions how fix this?
This is cause by the change stated in Xcode 6.3beta release notes:
Swift now detects discrepancies between overloading and overriding in
the Swift type system and the effective behavior seen via the
Objective-C runtime. (18391046, 18383574) For example, the following
conflict between the Objective-C setter for “property” in a class and
the method “setProperty” in its extension is now diagnosed:
class A : NSObject {
var property: String = "Hello" // note: Objective-C method 'setProperty:’
// previously declared by setter for
// 'property’ here
}
extension A {
func setProperty(str: String) { } // error: method ‘setProperty’
// redeclares Objective-C method
//'setProperty:’
}
To fix this you need to make all you method signatures unique (as Objective-C does not provide method overload)
Or don't inherit from NSObject if you need Swift only class.
Cappy: For the Standford problem I used simply this, because it looks like the Xcode Beta simply says that the operation: (Double, Double) -> Double is the same as operation: Double -> Double, I don't know if it is a bug or not...
But the code below works, but is NOT clean :(
func performOperation(r:String? = "2", operation: (Double, Double) -> Double) {
if operandStack.count >= 2 {
displayValue = operation(operandStack.removeLast(), operandStack.removeLast())
enter()
}
}
func performOperation(operation: Double -> Double) {
if operandStack.count >= 1 {
displayValue = operation(operandStack.removeLast())
enter()
}
}
As noted by #Kirsteins, Swift now detects conflicting symbols between Swift and Obj-C, and swift symbols that would cause Obj-C grief. In addition to the answer given, you can avoid this in general by specifying a required label for the additional types, thus changing the call signature:
import Foundation
extension NSObject {
func foo(d:Double, i:Int) { println("\(d), \(i)") }
func foo(withInt d:Int, i:Int) { println("\(d), \(i)") }
}
let no = NSObject()
no.foo(withInt:1, i: 2)
Beyond that though, and to answer your immediate question, you are trying to apply Obj-C idioms to Swift. What you really want, is to either implement didSet (most likely), or possibly set:
class WhatIDidLastSummer {
var vacation:Bool = false {
didSet {
// do something
}
}
var staycation:Bool {
get { return true }
set {
// do something
}
}
}