You could implement Range like below. So that range[i] = first + i * stride. This makes Range play nice with floats and other non-exact quantities.
/// Provide the capabilities needed to impliment Range. /// Ranges are indexed with an Int index between 0 and count - 1 inclusive and they return start + index * stride, where start and stride are Rangees. /// Via extensions Int and Double are Rangees. protocol Rangee { /// self += rhs mutating func add(rhs: Self) /// self -= rhs mutating func sub(rhs: Self) /// self *= rhs mutating func mult(rhs: Self) /// self /= rhs mutating func div(rhs: Self) /// Converts to an Int, truncating towards 0 if necessary var toInt: Int { get } /// Convert from an int, fails if the int is not representable static func fromInt(i: Int) -> Self } // Make Int a Rangee extension Int: Rangee { mutating func add(rhs: Int) { self += rhs } mutating func sub(rhs: Int) { self -= rhs } mutating func mult(rhs: Int) { self *= rhs } mutating func div(rhs: Int) { self /= rhs } var toInt: Int { return self } static func fromInt(i: Int) -> Int { return i } } // Make Double a Rangee extension Double: Rangee { mutating func add(rhs: Double) { self += rhs } mutating func sub(rhs: Double) { self -= rhs } mutating func mult(rhs: Double) { self *= rhs } mutating func div(rhs: Double) { self /= rhs } var toInt: Int { return Int(trunc(self)) } static func fromInt(i: Int) -> Double { return Double(i) } } /// An immutable-array-like collection that represents a potentially-inclusive range of Rangables such that `range[index] = first + index * stride`, where index in an Int between 0 and count - 1. /// `count = Int(trunc((last - first) / stride)) + 1`; /// therefore if `(last - first) / stride` is an integer, then the range includes last (or approximately last if underlying arithmetic type is non-exact). /// Name is MyRange to stop clash with Range, in practice woule be Range. struct MyRange<R: Rangee>: CollectionType { let first: R let last: R let stride: R let count: Int init(first: R, last: R, stride: R) { self.first = first self.last = last self.stride = stride self.count = MyRange.index(first: first, stride: stride, of: last) + 1 } private static func index(first first: R, stride: R, of: R) -> Int { var index = of index.sub(first) index.div(stride) return index.toInt } func index(of: R) -> Int { return MyRange.index(first: first, stride: stride, of: of) } var endIndex: Int { return count } var startIndex: Int { return 0 } // Note Range not MyRange needed for subscriptable range, in practice MyRange would be Range subscript(bounds: Range<Int>) -> MyRange<R> { return MyRange(first: self [bounds.startIndex], last: self[bounds.endIndex - 1], stride: self.stride) } subscript(index: Int) -> R { guard index >= 0 else { fatalError("Index, \(index), negative") } guard index < count else { fatalError("Index, \(index), >= count, \( count)") } var result = stride result.mult(R.fromInt(index)) result.add(first) return result } } -- Howard. On 29 March 2016 at 09:35, Erica Sadun via swift-evolution < swift-evolution@swift.org> wrote: > > > On Mar 28, 2016, at 3:54 PM, Dave Abrahams via swift-evolution < > swift-evolution@swift.org> wrote: > > > > > > on Mon Mar 28 2016, Erica Sadun <swift-evolution@swift.org> wrote: > > > >>> On Mar 28, 2016, at 3:25 PM, Dave Abrahams via swift-evolution > >>> <swift-evolution@swift.org> wrote: > >>> > >>> > >>> on Mon Mar 28 2016, Xiaodi Wu > >> > >>> <swift-evolution@swift.org > >>> <mailto:swift-evolution@swift.org>> > >>> wrote: > >>> > >>>> Right, Countable could refine Strideable. I'm no expert on this, but > >>>> some cursory reading suggests that the analogous feature in C++ simply > >>>> requires the type to have operator++ defined. Obviously, that won't > >>>> work for Swift 3.0... > >>> > >>> Hmm, instead of defining a new protocol (Countable), what if we just > use > >>> “Strideable where Stride : Integer” as a constraint? > >> > >> I like a differentiation between continuous and discrete things > >> although both can have ranges, membership, fences, > >> and a way to stride through them > > > > Strideable where Stride : Integer expresses just exactly that. Now if I > > could only get the type-checker to cooperate... > > I am ridiculously excited about what you're doing there. > Looking forward to beautiful floating point strides if for no > other reason than I can point out how well they work for math > in comparison to traditional for;;loops, so maybe people will > stop burning semicolons on my lawn. > > What are you feelings about disjoint and invertible intervals? > (I'll admit they currently fail the Lattner test[1], but they appeal to > my aesthetics) > > -- E > > [1] First rule of Lattner: A language change should provide a highly > focused > tweak to Swift with limited impact and a measurable benefit to developers > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution