// (c) 2021 and onwards Shiki Suen (MIT-NTL License).
// ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
import Foundation
extension Collection {
public func revolvedIndex(_ id: Int, clockwise: Bool = true, steps: Int = 1) -> Int {
if id < 0 || steps < 1 { return id }
var result = id
func revolvedIndexByOneStep(_ id: Int, clockwise: Bool = true) -> Int {
let newID = clockwise ? id + 1 : id - 1
if (0..<count).contains(newID) { return newID }
return clockwise ? 0 : count - 1
}
for _ in 0..<steps {
result = revolvedIndexByOneStep(result, clockwise: clockwise)
}
return result
}
}
extension Int {
public mutating func revolveAsIndex(with target: any Collection, clockwise: Bool = true, steps: Int = 1) {
if self < 0 || steps < 1 { return }
self = target.revolvedIndex(self, clockwise: clockwise, steps: steps)
}
}
// MARK: - Tests
let theArray: [Int] = [1,2,3,4]
var currentIndex = 0
for _ in 0..<8 {
currentIndex.revolveAsIndex(with: theArray)
print(currentIndex)
}
print("")
for _ in 0..<8 {
currentIndex.revolveAsIndex(with: theArray, clockwise: false)
print(currentIndex)
}
Why wouldn't you use the generic solution for Swift > 5.5?
Also, is this what you really want? Collections don't necessarily have indexes that are Int,nor, even if it is Int does the startIndex have to be 0 or the endIndex have to be count.
(You are probably aware of it:) Collection indices are not necessarily of type Int, and even if they are, the index of the first element need not be zero. What your revolvedIndex() operates on are “offsets” with respect to the startIndex of the collection, not indices into the collection.
The computation can be more efficiently done using the remainder operator %.
I am writing something friendly to early releases of Xcode 13 (which doesn't support Swift 5.6).
This snippet is helpful when designing something like the candidate list of an input method. When the last item is highlighted and you press the downArrow button, it revolves to the first index. I do admit that I don't have sufficient knowledges with Collection, still.
I think it's the easiest to use collection type and its index is of type Int and indices are always in the range 0 ..< self.count, so yes.
Collection is not just a protocol but it is one with associated types, which is why you can't just write revolveAsIndex(with target: Collection ... You can't really avoid generics as soon as you start doing anything interesting with Collection.
Sorry for a supplemental question.
Supposing that someone is gonna use your version instead, which license are you going to use? MIT or something else?