[swift-evolution] [Discussion][Expericment] D-like slicing syntax
David Hart
david at hartbit.com
Sun Feb 21 02:45:12 CST 2016
I’ve read the D documentation, I’ve used similar syntax in Ruby, and I agree that something along the same lines could be really expressive. I agree at least that the current Swift syntax for your example operations is much more verbose and surprising than should be.
> On 21 Feb 2016, at 01:41, Daniel Duan via swift-evolution <swift-evolution at swift.org> wrote:
>
> Hi all,
>
> A while ago there's a thread on adding Python's slicing syntax here:
> http://thread.gmane.org/gmane.comp.lang.swift.evolution/124/focus=261
>
> From it, a brief summary of the issues in Python's slicing syntax:
>
> 1. light syntax may suggest O(1) operation complexity to some.
> 2. negative index imposes runtime overhead
> 3. negative index masks fencepost errors (`foo(m-n)` supprises if you assume
> m > n)
>
> D's slicing syntax (https://dlang.org/d-array-article.html) was brought up as
> an alternative. It does a better job in suggesting "unusual" operation (if you
> treat subscripting with an index as normal). I attached a rudimentary
> implementation of it at the end. It's in not way aimed at being complete or
> ending up in stdlib. Hopefully, being able to play with it will generate more
> discussion on this topic :)
>
>
> // (if you prefer a gist: https://gist.github.com/dduan/5c54df865fdd7b6b7548)
> //
> // Incomplete:
> // '%' replaces the more ideal '$' (the latter can't be in name of operator)
> // where a open ended range is in the design, `nil` is used its place
> // force casting between Index.Distance and 'Int'
> // only on CollectionType, but a version for string is not hard to add
>
> public struct Offset { let value: Int }
>
> prefix operator %+ {}
> prefix operator %- {}
>
> prefix func %+(offset: Int) -> Offset {
> return Offset(value: offset)
> }
> prefix func %-(offset: Int) -> Offset {
> return Offset(value: -offset)
> }
>
> internal func normalize(start: Int?, end: Int?, total: Int) -> (Int, Int) {
> var actualStart = start ?? 0
> var actualEnd = end ?? total
> actualStart = actualStart < 0 ? total + actualStart : actualStart
> actualEnd = actualEnd < 0 ? total + actualEnd : actualEnd
> // uncomment the following for a much more forgiving index behavior
> // actualStart = actualStart < 0 ? 0 : actualStart
> // actualEnd = actualEnd < 0 ? 0 : actualEnd
> // let safeEnd = min(actualEnd, total)
> // return (min(actualStart, safeEnd), safeEnd)
> return (actualStart, actualEnd)
> }
>
> extension CollectionType {
> public subscript(start:Offset?, end:Offset?) -> Self.SubSequence {
> let (safeStart, safeEnd) = normalize(
> start?.value, end: end?.value, total: self.count as! Int)
> let safeStartIndex = startIndex.advancedBy(
> safeStart as! Self.Index.Distance)
> let safeEndIndex = startIndex.advancedBy(
> safeEnd as! Self.Index.Distance)
> return self[safeStartIndex..<safeEndIndex]
> }
>
> public subscript(index: Offset) -> Self.Generator.Element {
> let (safeStart, _) = normalize(
> index.value, end: 0, total: self.count as! Int)
> return self[startIndex.advancedBy(safeStart as! Self.Index.Distance)]
> }
> }
>
>
> let s = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>
> // equavelent in Swift Python Result
> s[%+2] // s[s.startIndex.advancedBy(2)] s[2] 2
> s[%-2] // s[s.endIndex.advancedBy(-2)] s[-2] 8
> s[%+2, %-3] // s.dropFirst(2).dropLast(3) s[2:-2] [2, 3, 4, 5, 6]
> s[%-5, nil] // s.dropFirst(s.count - 5) s[-5:] [5, 6, 7, 8, 9]
> s[nil, %-8] // s.dropLast(8) s[:-8] [0, 1]
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
More information about the swift-evolution
mailing list