[swift-evolution] Pitch: Range return values for String Insert/Replace methods
Ben Cohen
ben_cohen at apple.com
Tue Mar 14 19:25:41 CDT 2017
Hi Charles,
As part of the String redesign in Swift 4, these methods on String are intended to be part of String’s conformance to RangeReplaceableCollection. As such, this proposal should be phrased in terms of a change to that protocol, rather than to String.
Couple of additional things to note regarding this:
- this would also need to consider the source compatibility consequences for any existing adopters of RRC.
- RRC is designed such that the minimum you need to implement is a single replaceSubrange call (and an init) and you get the other methods "for free". See "Conforming to the RangeReplaceableCollection Protocol” in the docs for details: https://developer.apple.com/reference/swift/rangereplaceablecollection <https://developer.apple.com/reference/swift/rangereplaceablecollection>, and the implementation for gorier details: https://github.com/apple/swift/blob/master/stdlib/public/core/RangeReplaceableCollection.swift.gyb
Regards,
Ben
> On Mar 14, 2017, at 9:21 AM, Charles Srstka via swift-evolution <swift-evolution at swift.org> wrote:
>
> MOTIVATION:
>
> Swift strings support a few methods for inserting and replacing things in the middle of them:
>
> mutating func insert(_ newElement: Character, at i: String.Index)
>
> mutating func insert<S : Collection where S.Iterator.Element == Character>(contentsOf newElements: S, at i: String.Index)
>
> mutating func replaceSubrange(_ bounds: ClosedRange<String.Index>, with newElements: String)
>
> mutating func replaceSubrange(_ bounds: Range<String.Index>, with newElements: String)
>
> mutating func replaceSubrange<C where C : Collection, C.Iterator.Element == Character>(_: ClosedRange<String.Index>, with: C)
>
> mutating func replaceSubrange<C where C : Collection, C.Iterator.Element == Character>(_ bounds: Range<String.Index>, with newElements: C)
>
> These work well, but sometimes is advantageous to know the range of the portion of the string taken up by the inserted elements—for example, if one is creating a UI element, one may want to highlight the inserted text. In the old days when strings were defined in terms of UTF-16 code units, this was easy enough—just make a range starting at the insertion point and with the length of the string you just inserted. In Swift it is awkward and verbose:
>
> let insertedRange = replacementRange.lowerBound..<string.index(replacementRange.lowerBound, offsetBy: replacementString.distance(from: replacementString.startIndex, to: replacementString.endIndex))
>
> PROPOSED SOLUTION:
>
> Introduce a return value on the insert and replace methods that contains the range of the inserted characters or string:
>
> @discardableResult mutating func insert(_ newElement: Character, at i: String.Index) -> Range<String.Index>
>
> @discardableResult mutating func insert<S : Collection where S.Iterator.Element == Character>(contentsOf newElements: S, at i: String.Index) -> Range<String.Index>
>
> @discardableResult mutating func replaceSubrange(_ bounds: ClosedRange<String.Index>, with newElements: String) -> Range<String.Index>
>
> @discardableResult mutating func replaceSubrange(_ bounds: Range<String.Index>, with newElements: String) -> Range<String.Index>
>
> @discardableResult mutating func replaceSubrange<C where C : Collection, C.Iterator.Element == Character>(_: ClosedRange<String.Index>, with: C) -> Range<String.Index>
>
> @discardableResult mutating func replaceSubrange<C where C : Collection, C.Iterator.Element == Character>(_ bounds: Range<String.Index>, with newElements: C) -> Range<String.Index>
>
> The return value would contain the range of the portion of the string now occupied by what was inserted.
>
> If this change is considered acceptable, it could also be applied to the equivalent methods on RangeReplaceableCollection.
>
> IMPACT ON EXISTING CODE:
>
> The @discardableResult attribute would ensure that existing code would continue to work as is. The change in the signatures, however, would affect ABI compatibility.
>
> If the change is made to the protocols, however, this would affect source compatibility, as concrete types conforming to the protocols would need to be updated.
>
> ALTERNATIVES CONSIDERED:
>
> If there are performance concerns with generating the ranges, String could simply have two versions of each method, one returning a range and one returning Void.
>
> Charles
>
> _______________________________________________
> 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/20170314/a91abf51/attachment.html>
More information about the swift-evolution
mailing list