I don't have a strong opinion; are we sure enough that this is what we want the postfix operator … to be for? For instance, C++ uses it a lot with variadic templates.
> Le 12 avr. 2017 à 13:21, David Hart via swift-evolution > <swift-evolution@swift.org> a écrit : > > I remember being against this feature when it was first discussed long ago. > But I’ve since appreciated how elegant it is. I also like the i… was chosen > instead of i..< > > I guess Range would be a better name for the generic protocol to represent > all ranges. But its too late for that now. Correct? > >> On 12 Apr 2017, at 18:40, Ben Cohen via swift-evolution >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >> >> Hi Swift community, >> >> Another proposal pitch. These operators were mentioned briefly in the String >> manifesto as prefixing/suffixing is very common with strings. >> >> Online copy here: >> https://github.com/airspeedswift/swift-evolution/blob/71b819d30676c44234bac1aa999961fc5c39bcf3/proposals/NNNN-OneSidedRanges.md >> >> <https://github.com/airspeedswift/swift-evolution/blob/71b819d30676c44234bac1aa999961fc5c39bcf3/proposals/NNNN-OneSidedRanges.md> >> One-sided Ranges >> >> Proposal: SE-NNNN >> <file:///Users/ben_cohen/Documents/swift-evolution/proposals/NNNN-filename.md> >> Authors: Ben Cohen <https://github.com/airspeedswift>, Dave Abrahams >> <https://github.com/dabrahams>, Brent Royal-Gordon >> <https://github.com/brentdax> >> Review Manager: TBD >> Status: Awaiting review >> Introduction >> >> This proposal introduces the concept of a “one-sided” range, created via >> prefix/postfix versions of the existing range operators. >> >> It also introduces a new protocol, RangeExpression, to simplify the creation >> of methods that take different kinds of ranges. >> >> Motivation >> >> It is common, given an index into a collection, to want a slice up to or >> from that index versus the start/end. >> >> For example (assuming String is once more a Collection): >> >> let s = "Hello, World!" >> let i = s.index(where: ",") >> let greeting = s[s.startIndex..<i] >> When performing lots of slicing like this, the verbosity of repeating >> s.startIndex is tiresome to write and harmful to readability. >> >> Swift 3’s solution to this is a family of methods: >> >> let greeting = s.prefix(upTo: i) >> let withComma = s.prefix(through: i) >> let location = s.suffix(from: i) >> The two very different-looking ways to perform a similar task is jarring. >> And as methods, the result cannot be used as an l-value. >> >> A variant of the one-sided slicing syntax found in Python (i.e. s[i:]) is >> proposed to resolve this. >> >> Proposed solution >> >> Introduce a one-sided range syntax, where the “missing” side is inferred to >> be the start/end: >> >> // half-open right-handed range >> let greeting = s[..<i] >> // closed right-handed range >> let withComma = s[...i] >> // left-handed range (no need for half-open variant) >> let location = s[i...] >> Additionally, when the index is a countable type, i... should form a >> Sequence that counts up from i indefinitely. This is useful in forming >> variants of Sequence.enumerated() when you either want them non-zero-based >> i.e. zip(1..., greeting), or want to flip the order i.e. zip(greeting, 0...). >> >> This syntax would supercede the existing prefix and suffix operations that >> take indices, which will be deprecated in a later release. Note that the >> versions that take distances are not covered by this proposal, and would >> remain. >> >> This will require the introduction of new range types (e.g. >> PartialRangeThrough). There are already multiple range types (e.g. >> ClosedRange, CountableHalfOpenRange), which require overloads to allow them >> to be used whereever a Range can be. >> >> To unify these different range types, a new protocol, RangeExpression will >> be created and all ranges conformed to it. Existing overloads taking >> concrete types other than Range can then be replaced with a single generic >> method that takes a RangeExpression, converts it to a Range, and then >> forward the method on. >> >> A generic version of ~= will also be implemented for all range expressions: >> >> switch i { >> case 9001...: print("It’s over NINE THOUSAAAAAAAND") >> default: print("There's no way that can be right!") >> } >> The existing concrete overloads that take ranges other than Range will be >> deprecated in favor of generic ones that take a RangeExpression. >> >> Detailed design >> >> Add the following to the standard library: >> >> (a fuller work-in-progress implementation can be found here: >> https://github.com/apple/swift/pull/8710 >> <https://github.com/apple/swift/pull/8710>) >> >> NOTE: The following is subject to change depending on pending compiler >> features. Methods may actually be on underscored protocols, and then moved >> once recursive protocols are implemented. Types may be collapsed using >> conditional conformance. This should not matter from a usage perspective – >> users are not expected to use these types directly or override any of the >> behaviors in their own types. Any final implementation will follow the below >> in spirit if not in practice. >> >> public protocol RangeExpression { >> associatedtype Bound: Comparable >> >> /// Returns `self` expressed as a range of indices within `collection`. >> /// >> /// -Parameter collection: The collection `self` should be >> /// relative to. >> /// >> /// -Returns: A `Range<Bound>` suitable for slicing `collection`. >> /// The return value is *not* guaranteed to be inside >> /// its bounds. Callers should apply the same preconditions >> /// to the return value as they would to a range provided >> /// directly by the user. >> func relative<C: _Indexable>(to collection: C) -> Range<Bound> where >> C.Index == Bound >> >> func contains(_ element: Bound) -> Bool >> } >> >> extension RangeExpression { >> public static func ~= (pattern: Self, value: Bound) -> Bool >> } >> >> prefix operator ..< >> public struct PartialRangeUpTo<T: Comparable>: RangeExpression { >> public init(_ upperBound: T) { self.upperBound = upperBound } >> public let upperBound: T >> } >> extension Comparable { >> public static prefix func ..<(x: Self) -> PartialRangeUpTo<Self> >> } >> >> prefix operator ... >> public struct PartialRangeThrough<T: Comparable>: RangeExpression { >> public init(_ upperBound: T) >> public let upperBound: T >> } >> extension Comparable { >> public static prefix func ...(x: Self) -> PartialRangeThrough<Self> >> } >> >> postfix operator ... >> public struct PartialRangeFrom<T: Comparable>: RangeExpression { >> public init(_ lowerBound: T) >> public let lowerBound: T >> } >> extension Comparable { >> public static postfix func ...(x: Self) -> PartialRangeFrom<Self> >> } >> >> // The below relies on Conditional Conformance. Pending that feature, >> // this may require an additional CountablePartialRangeFrom type temporarily. >> extension PartialRangeFrom: Sequence >> where Index: _Strideable, Index.Stride : SignedInteger >> >> >> extension Collection { >> public subscript<R: RangeExpression>(r: R) -> SubSequence >> where R.Bound == Index { get } >> } >> extension MutableCollection { >> public subscript<R: RangeExpression>(r: R) -> SubSequence >> where R.Bound == Index { get set } >> } >> >> extension RangeReplaceableColleciton { >> public mutating func replaceSubrange<C: Collection, R: RangeExpression>( >> _ subrange: ${Range}<Index>, with newElements: C >> ) where C.Iterator.Element == Iterator.Element, R.Bound == Index >> >> public mutating func removeSubrange<R: RangeExpression>( >> _ subrange: ${Range}<Index> >> ) where R.Bound == Index >> } >> Additionally, these new ranges will implement appropriate protocols such as >> CustomStringConvertible. >> >> It is important to note that these new methods and range types are >> extensions only. They are not protocol requirements, as they should not need >> to be customized for specific collections. They exist only as shorthand to >> expand out to the full slicing operation. >> >> The prefix and suffix methods that take an index are currently protocol >> requirements, but should not be. This proposal will fix that as a >> side-effect. >> >> Where PartialRangeFrom is a Sequence, it is left up to the type of Index to >> control the behavior when the type is incremented past its bounds. In the >> case of an Int, the iterator will trap when iterating past Int.max. Other >> types, such as a BigInt that could be incremented indefinitely, would behave >> differently. >> >> Source compatibility >> >> The new operators/types are purely additive so have no source compatibility >> consequences. Replacing the overloads taking concrete ranges other than >> Range with a single generic version is source compatible. prefix and suffix >> will be deprecated in Swift 4 and later removed. >> >> Effect on ABI stability >> >> The prefix/suffix methods being deprecated should be eliminated before >> declaring ABI stability. >> >> Effect on API resilience >> >> The new operators/types are purely additive so have no resilience >> consequences. >> >> Alternatives considered >> >> i... is favored over i..< because the latter is ugly. We have to pick one, >> two would be redundant and likely to cause confusion over which is the >> “right” one. Either would be reasonable on pedantic correctness grounds – (i >> as Int)... includes Int.max consistent with ..., whereas a[i...] is >> interpreted as a[i..<a.endIndex] consistent with i..<. >> >> It might be nice to consider extend this domain-specific language inside the >> subscript in other ways. For example, to be able to incorporate the index >> distance versions of prefix, or add distance offsets to the indices used >> within the subscript. This proposal explicitly avoids proposals in this >> area. Such ideas would be considerably more complex to implement, and would >> make a good project for investigation by an interested community member, but >> would not fit within the timeline for Swift 4. >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org <mailto: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
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution