[swift-evolution] Feature proposal: Range operator with step
Howard Lovatt
howard.lovatt at gmail.com
Mon Mar 28 18:05:48 CDT 2016
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 at swift.org> wrote:
>
> > On Mar 28, 2016, at 3:54 PM, Dave Abrahams via swift-evolution <
> swift-evolution at swift.org> wrote:
> >
> >
> > on Mon Mar 28 2016, Erica Sadun <swift-evolution at swift.org> wrote:
> >
> >>> On Mar 28, 2016, at 3:25 PM, Dave Abrahams via swift-evolution
> >>> <swift-evolution at swift.org> wrote:
> >>>
> >>>
> >>> on Mon Mar 28 2016, Xiaodi Wu
> >>
> >>> <swift-evolution at swift.org
> >>> <mailto:swift-evolution at 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 at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160329/ddab9904/attachment.html>
More information about the swift-evolution
mailing list