>> Actually, it would need to be something like
>> `calendar[startDate..<endDate, unit: .Day].striding(by: 1)`, because
>> NSCalendarUnit is not itself a stride, it is the *unit* of the
>> stride. 
> 
> Maybe:
> 
>  calendar.days[startDate..<endDate].striding(by: 1)

I've been leaning towards parameters for additional flexibility, but the 
difference there is only slightly more than bikeshedding.

> However, it doesn't explain why
> 
>  calendar[startDate..<endDate, unit: .Day].striding(by: 1)
> 
> “doesn't quite help.”  It seems to me that 
> 
>  calendar[startDate..<endDate, unit: .Day]
> 
> does factor in the calendar and unit.

Yes, it does—as long as Strideable changes so that the instance created by this 
expression participates in the striding. My point is that, as long as the 
operations in Strideable are performed on one of the two strides, the "range" 
we're moving over can't be involved enough to help. Striding has to be done 
with the assistance of the instance owning the start and end, not just the 
start and end themselves.

Basically, what I'm saying is that Strideable needs a redesign along the lines 
of the indexing system. We redesigned indexing so that the collection 
manipulates the indexes, rather than the indexes manipulating themselves, 
because the indexes don't always have enough information to do the job. We need 
to do the same thing with Strideable.

>> For example, suppose you modify `Strideable` so that, instead of
>> applying to the values participating in the striding, it applies to
>> the instance containing those values:
>> 
>>      public protocol Strideable {
>>              associatedtype Element: Comparable
>>              associatedtype Stride: SignedNumber
>> 
>>              var start: Value
>>              var end: Value
>> 
>>              public func distance(from earlier: Element, to later: Element) 
>> -> Stride
>>              public func advance(element: Element, by stride: Stride) -> 
>> Element
>>      }
> 
> Presumably you mean for Strideable to have a striding(by:_) method as well?

Yes, there would be an extension method like that (or there would be a `func 
stride<StrideableType: Strideable>(over: StrideableType, by: 
StrideableType.Stride) -> …`, which is the same thing). I didn't include it 
because it's not a requirement imposed on the conforming type.

> If so, how is this fundamentally different from Collection?  Shouldn't
> every Collection support this?

Huh, interesting. Very, very interesting.

Strideable is more widely applicable than Collection; for instance, a 
Range<Double> can't be a Collection (except via `nextafter`), but it is 
Strideable. But every RandomAccessCollection can be Strideable. (So could any 
BidirectionalCollection, for that matter, although it would be slower.) 
`array.striding(by: 2)` is a coherent and useful operation.

So yes, I think every Collection (with a suitable index) could be Strideable. 
But there are Strideable things which aren't collections.

> Except we don't have that capability today.  Instead we'd be using
> overloads of ..< and ... to produce more-capable range types, c.f.  
> https://github.com/apple/swift/blob/swift-3-indexing-model/stdlib/public/core/Range.swift#L504
> https://github.com/apple/swift/blob/swift-3-indexing-model/stdlib/public/core/Range.swift#L519

That works too, I suppose. You would end up with a StrideableRange "between" 
your current CountableRange (which is a Collection) and Range (which is a 
glorified tuple).

-- 
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to