I spent some time coding on Linux with Swift 3 (latest developement snapshot) and corelibs-foundation and I’ve hit one major hurdle: passing and converting NSRange and Range around between the different stdlib and Foundation APIs - specifically in regards to String.
Is there a plan to simplify those pain points by converting all corelibs-foundation APIs to accept/return Range on String instead of NSRange? In that case, can’t we get rid of NSRange completely?
One idea that had come up before was to bridge NSRange to Range<Int>, although it wouldn’t completely eliminate NSRange because the two types are not representationally identical.
- Doug
···
On May 8, 2016, at 2:10 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:
Hello Swift-Evolution,
I spent some time coding on Linux with Swift 3 (latest developement snapshot) and corelibs-foundation and I’ve hit one major hurdle: passing and converting NSRange and Range around between the different stdlib and Foundation APIs - specifically in regards to String.
Is there a plan to simplify those pain points by converting all corelibs-foundation APIs to accept/return Range on String instead of NSRange? In that case, can’t we get rid of NSRange completely?
Why wouldn't it completely eliminate NSRange? Are you thinking of NSNotFound? Could we migrate those APIs to return an Optional Range<Int>?
···
On 10 May 2016, at 05:49, Douglas Gregor <dgregor@apple.com> wrote:
On May 8, 2016, at 2:10 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:
Hello Swift-Evolution,
I spent some time coding on Linux with Swift 3 (latest developement snapshot) and corelibs-foundation and I’ve hit one major hurdle: passing and converting NSRange and Range around between the different stdlib and Foundation APIs - specifically in regards to String.
Is there a plan to simplify those pain points by converting all corelibs-foundation APIs to accept/return Range on String instead of NSRange? In that case, can’t we get rid of NSRange completely?
One idea that had come up before was to bridge NSRange to Range<Int>, although it wouldn’t completely eliminate NSRange because the two types are not representationally identical.
Because NSRange has a different representation than Range<Int> (start+length vs. start/end), a pointer-to-NSRange has to come in as Unsafe(Mutable)Pointer<NSRange> rather than Unsafe(Mutable)Pointer<Range<Int>>. It’s the same reason that (e.g.), an NSArray** parameter comes in as UnsafeMutablePointer<NSArray> rather than UnsafeMutablePointer<[AnyObject]>.
Are you thinking of NSNotFound? Could we migrate those APIs to return an Optional Range<Int>?
If you had annotations on the APIs to say that they use NSNotFound as a sentinel, yes.
- Doug
···
On May 9, 2016, at 11:23 PM, David Hart <david@hartbit.com> wrote:
On 10 May 2016, at 05:49, Douglas Gregor <dgregor@apple.com> wrote:
On May 8, 2016, at 2:10 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:
Hello Swift-Evolution,
I spent some time coding on Linux with Swift 3 (latest developement snapshot) and corelibs-foundation and I’ve hit one major hurdle: passing and converting NSRange and Range around between the different stdlib and Foundation APIs - specifically in regards to String.
Is there a plan to simplify those pain points by converting all corelibs-foundation APIs to accept/return Range on String instead of NSRange? In that case, can’t we get rid of NSRange completely?
One idea that had come up before was to bridge NSRange to Range<Int>, although it wouldn’t completely eliminate NSRange because the two types are not representationally identical.
But it’s reasonably implementable? I guess the answer is yes if you have already faced the same bridging concerns with NSArray/Array. I’de really like this going forward, but I don’t know how confident I am in writing a proposal.
···
On 10 May 2016, at 08:29, Douglas Gregor <dgregor@apple.com> wrote:
On May 9, 2016, at 11:23 PM, David Hart <david@hartbit.com> wrote:
Why wouldn't it completely eliminate NSRange?
Because NSRange has a different representation than Range<Int> (start+length vs. start/end), a pointer-to-NSRange has to come in as Unsafe(Mutable)Pointer<NSRange> rather than Unsafe(Mutable)Pointer<Range<Int>>. It’s the same reason that (e.g.), an NSArray** parameter comes in as UnsafeMutablePointer<NSArray> rather than UnsafeMutablePointer<[AnyObject]>.
Are you thinking of NSNotFound? Could we migrate those APIs to return an Optional Range<Int>?
If you had annotations on the APIs to say that they use NSNotFound as a sentinel, yes.
- Doug
On 10 May 2016, at 05:49, Douglas Gregor <dgregor@apple.com> wrote:
On May 8, 2016, at 2:10 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:
Hello Swift-Evolution,
I spent some time coding on Linux with Swift 3 (latest developement snapshot) and corelibs-foundation and I’ve hit one major hurdle: passing and converting NSRange and Range around between the different stdlib and Foundation APIs - specifically in regards to String.
Is there a plan to simplify those pain points by converting all corelibs-foundation APIs to accept/return Range on String instead of NSRange? In that case, can’t we get rid of NSRange completely?
One idea that had come up before was to bridge NSRange to Range<Int>, although it wouldn’t completely eliminate NSRange because the two types are not representationally identical.
But it’s reasonably implementable? I guess the answer is yes if you have already faced the same bridging concerns with NSArray/Array. I’de really like this going forward, but I don’t know how confident I am in writing a proposal.
Yes, it's implementable. We do something similar to turn Darwin's BOOL into Swift's Bool even though they are representationally different.
- Doug
···
Sent from my iPhone
On May 10, 2016, at 12:14 AM, David Hart <david@hartbit.com> wrote:
On 10 May 2016, at 08:29, Douglas Gregor <dgregor@apple.com> wrote:
On May 9, 2016, at 11:23 PM, David Hart <david@hartbit.com> wrote:
Why wouldn't it completely eliminate NSRange?
Because NSRange has a different representation than Range<Int> (start+length vs. start/end), a pointer-to-NSRange has to come in as Unsafe(Mutable)Pointer<NSRange> rather than Unsafe(Mutable)Pointer<Range<Int>>. It’s the same reason that (e.g.), an NSArray** parameter comes in as UnsafeMutablePointer<NSArray> rather than UnsafeMutablePointer<[AnyObject]>.
Are you thinking of NSNotFound? Could we migrate those APIs to return an Optional Range<Int>?
If you had annotations on the APIs to say that they use NSNotFound as a sentinel, yes.
- Doug
On 10 May 2016, at 05:49, Douglas Gregor <dgregor@apple.com> wrote:
On May 8, 2016, at 2:10 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:
Hello Swift-Evolution,
I spent some time coding on Linux with Swift 3 (latest developement snapshot) and corelibs-foundation and I’ve hit one major hurdle: passing and converting NSRange and Range around between the different stdlib and Foundation APIs - specifically in regards to String.
Is there a plan to simplify those pain points by converting all corelibs-foundation APIs to accept/return Range on String instead of NSRange? In that case, can’t we get rid of NSRange completely?
One idea that had come up before was to bridge NSRange to Range<Int>, although it wouldn’t completely eliminate NSRange because the two types are not representationally identical.
One particular concern we've had is that many NSRanges aren’t Range<Int>; they’re Range<String.UTF16Index>. I suppose things wouldn’t get any worse there, though.
Jordan
···
On May 10, 2016, at 00:14, David Hart via swift-evolution <swift-evolution@swift.org> wrote:
But it’s reasonably implementable? I guess the answer is yes if you have already faced the same bridging concerns with NSArray/Array. I’de really like this going forward, but I don’t know how confident I am in writing a proposal.
On 10 May 2016, at 08:29, Douglas Gregor <dgregor@apple.com> wrote:
On May 9, 2016, at 11:23 PM, David Hart <david@hartbit.com> wrote:
Why wouldn't it completely eliminate NSRange?
Because NSRange has a different representation than Range<Int> (start+length vs. start/end), a pointer-to-NSRange has to come in as Unsafe(Mutable)Pointer<NSRange> rather than Unsafe(Mutable)Pointer<Range<Int>>. It’s the same reason that (e.g.), an NSArray** parameter comes in as UnsafeMutablePointer<NSArray> rather than UnsafeMutablePointer<[AnyObject]>.
Are you thinking of NSNotFound? Could we migrate those APIs to return an Optional Range<Int>?
If you had annotations on the APIs to say that they use NSNotFound as a sentinel, yes.
- Doug
On 10 May 2016, at 05:49, Douglas Gregor <dgregor@apple.com> wrote:
On May 8, 2016, at 2:10 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:
Hello Swift-Evolution,
I spent some time coding on Linux with Swift 3 (latest developement snapshot) and corelibs-foundation and I’ve hit one major hurdle: passing and converting NSRange and Range around between the different stdlib and Foundation APIs - specifically in regards to String.
Is there a plan to simplify those pain points by converting all corelibs-foundation APIs to accept/return Range on String instead of NSRange? In that case, can’t we get rid of NSRange completely?
One idea that had come up before was to bridge NSRange to Range<Int>, although it wouldn’t completely eliminate NSRange because the two types are not representationally identical.
Would it be feasible to annotate those and have them appropriately
converted to Range<String.UTF16Index> upon crossing the bridge? Thinking
in particular of TextKit and friends — it'd away with quite a lot of the
pain of, e.g., not having a native struct-y AttributedString.
Cheers!
Zachary Waldowski
zach@waldowski.me
···
On Tue, May 10, 2016, at 12:37 PM, Jordan Rose via swift-evolution wrote:
One particular concern we've had is that many NSRanges aren’t
Range<Int>; they’re Range<String.UTF16Index>. I suppose things
wouldn’t get any *worse* there, though.
Jordan
On May 10, 2016, at 00:14, David Hart via swift-evolution <swift- >> evolution@swift.org> wrote:
But it’s reasonably implementable? I guess the answer is yes if you
have already faced the same bridging concerns with NSArray/Array.
I’de really like this going forward, but I don’t know how confident I
am in writing a proposal.
On 10 May 2016, at 08:29, Douglas Gregor <dgregor@apple.com> wrote:
On May 9, 2016, at 11:23 PM, David Hart <david@hartbit.com> wrote:
Why wouldn't it completely eliminate NSRange?
Because NSRange has a different representation than Range<Int>
(start+length vs. start/end), a pointer-to-NSRange has to come in as
Unsafe(Mutable)Pointer<NSRange> rather than
Unsafe(Mutable)Pointer<Range<Int>>. It’s the same reason that
(e.g.), an NSArray** parameter comes in as
UnsafeMutablePointer<NSArray> rather than
UnsafeMutablePointer<[AnyObject]>.
Are you thinking of NSNotFound? Could we migrate those APIs to
return an Optional Range<Int>?
If you had annotations on the APIs to say that they use NSNotFound
as a sentinel, yes.
- Doug
On 10 May 2016, at 05:49, Douglas Gregor <dgregor@apple.com> >>>>> wrote:
On May 8, 2016, at 2:10 PM, David Hart via swift-evolution <swift- >>>>>> evolution@swift.org> wrote:
Hello Swift-Evolution,
I spent some time coding on Linux with Swift 3 (latest
developement snapshot) and corelibs-foundation and I’ve hit one
major hurdle: passing and converting NSRange and Range around
between the different stdlib and Foundation APIs - specifically
in regards to String.
Is there a plan to simplify those pain points by converting all
corelibs-foundation APIs to accept/return Range on String instead
of NSRange? In that case, can’t we get rid of NSRange completely?
One idea that had come up before was to bridge NSRange to
Range<Int>, although it wouldn’t completely eliminate NSRange
because the two types are not representationally identical.
We thought about that too. The problem is that it’s not always obvious what NSString or NSAttributedString the indexes refer to. For example, most of the NSRegularExpression APIs produce matches in the form of NSTextCheckingResult, which then doesn’t have a reference to the original string.
Jordan
···
On May 10, 2016, at 13:43, Zach Waldowski via swift-evolution <swift-evolution@swift.org> wrote:
Would it be feasible to annotate those and have them appropriately converted to Range<String.UTF16Index> upon crossing the bridge? Thinking in particular of TextKit and friends — it'd away with quite a lot of the pain of, e.g., not having a native struct-y AttributedString.
On Tue, May 10, 2016, at 12:37 PM, Jordan Rose via swift-evolution wrote:
One particular concern we've had is that many NSRanges aren’t Range<Int>; they’re Range<String.UTF16Index>. I suppose things wouldn’t get any worse there, though.
Jordan
On May 10, 2016, at 00:14, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
But it’s reasonably implementable? I guess the answer is yes if you have already faced the same bridging concerns with NSArray/Array. I’de really like this going forward, but I don’t know how confident I am in writing a proposal.
On 10 May 2016, at 08:29, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:
On May 9, 2016, at 11:23 PM, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:
Why wouldn't it completely eliminate NSRange?
Because NSRange has a different representation than Range<Int> (start+length vs. start/end), a pointer-to-NSRange has to come in as Unsafe(Mutable)Pointer<NSRange> rather than Unsafe(Mutable)Pointer<Range<Int>>. It’s the same reason that (e.g.), an NSArray** parameter comes in as UnsafeMutablePointer<NSArray> rather than UnsafeMutablePointer<[AnyObject]>.
Are you thinking of NSNotFound? Could we migrate those APIs to return an Optional Range<Int>?
If you had annotations on the APIs to say that they use NSNotFound as a sentinel, yes.
- Doug
On 10 May 2016, at 05:49, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:
On May 8, 2016, at 2:10 PM, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Hello Swift-Evolution,
I spent some time coding on Linux with Swift 3 (latest developement snapshot) and corelibs-foundation and I’ve hit one major hurdle: passing and converting NSRange and Range around between the different stdlib and Foundation APIs - specifically in regards to String.
Is there a plan to simplify those pain points by converting all corelibs-foundation APIs to accept/return Range on String instead of NSRange? In that case, can’t we get rid of NSRange completely?
One idea that had come up before was to bridge NSRange to Range<Int>, although it wouldn’t completely eliminate NSRange because the two types are not representationally identical.
By the way, this doesn’t mean it can’t be done, or that we can’t decide on some kind of partial solution! It just means that it needs to be carefully considered and explicitly addressed.
Jordan
···
On May 10, 2016, at 15:49, Jordan Rose <jordan_rose@apple.com> wrote:
We thought about that too. The problem is that it’s not always obvious what NSString or NSAttributedString the indexes refer to. For example, most of the NSRegularExpression APIs produce matches in the form of NSTextCheckingResult, which then doesn’t have a reference to the original string.
Jordan
On May 10, 2016, at 13:43, Zach Waldowski via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Would it be feasible to annotate those and have them appropriately converted to Range<String.UTF16Index> upon crossing the bridge? Thinking in particular of TextKit and friends — it'd away with quite a lot of the pain of, e.g., not having a native struct-y AttributedString.
On Tue, May 10, 2016, at 12:37 PM, Jordan Rose via swift-evolution wrote:
One particular concern we've had is that many NSRanges aren’t Range<Int>; they’re Range<String.UTF16Index>. I suppose things wouldn’t get any worse there, though.
Jordan
On May 10, 2016, at 00:14, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
But it’s reasonably implementable? I guess the answer is yes if you have already faced the same bridging concerns with NSArray/Array. I’de really like this going forward, but I don’t know how confident I am in writing a proposal.
On 10 May 2016, at 08:29, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:
On May 9, 2016, at 11:23 PM, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:
Why wouldn't it completely eliminate NSRange?
Because NSRange has a different representation than Range<Int> (start+length vs. start/end), a pointer-to-NSRange has to come in as Unsafe(Mutable)Pointer<NSRange> rather than Unsafe(Mutable)Pointer<Range<Int>>. It’s the same reason that (e.g.), an NSArray** parameter comes in as UnsafeMutablePointer<NSArray> rather than UnsafeMutablePointer<[AnyObject]>.
Are you thinking of NSNotFound? Could we migrate those APIs to return an Optional Range<Int>?
If you had annotations on the APIs to say that they use NSNotFound as a sentinel, yes.
- Doug
On 10 May 2016, at 05:49, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:
On May 8, 2016, at 2:10 PM, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Hello Swift-Evolution,
I spent some time coding on Linux with Swift 3 (latest developement snapshot) and corelibs-foundation and I’ve hit one major hurdle: passing and converting NSRange and Range around between the different stdlib and Foundation APIs - specifically in regards to String.
Is there a plan to simplify those pain points by converting all corelibs-foundation APIs to accept/return Range on String instead of NSRange? In that case, can’t we get rid of NSRange completely?
One idea that had come up before was to bridge NSRange to Range<Int>, although it wouldn’t completely eliminate NSRange because the two types are not representationally identical.
Right, I 100% get it. :) This is a difficult problem space, and I'm sure
you folks are aware that that difficulty is also reflected in how brutal
it is to use all of these derivative string-range-based things in Swift
right now. In this case, having no answer to this problem is worse than
not having the API at all — check Stack Overflow or GitHub for how often
a "just paste this in" String.Index.init(_: Int) comes up.
As far as NSTextCheckingResult goes, its ranges are always in the
"indices" always in the space of the original string… do I have that
right? So it would be programmer error to use those ranges in the wrong
string just like it is with any Range<String.UTF16Index> today.
Zach Waldowski
···
On Tue, May 10, 2016, at 06:51 PM, Jordan Rose wrote:
By the way, this doesn’t mean it can’t be done, or that we can’t
decide on some kind of partial solution! It just means that it needs
to be carefully considered and explicitly addressed.
Jordan
On May 10, 2016, at 15:49, Jordan Rose <jordan_rose@apple.com> wrote:
We thought about that too. The problem is that it’s not always
obvious what NSString or NSAttributedString the indexes refer to. For
example, most of the NSRegularExpression APIs produce matches in the
form of NSTextCheckingResult, which then doesn’t have a reference to
the original string.
Jordan
On May 10, 2016, at 13:43, Zach Waldowski via swift-evolution <swift- >>> evolution@swift.org> wrote:
Would it be feasible to annotate those and have them appropriately
converted to Range<String.UTF16Index> upon crossing the bridge?
Thinking in particular of TextKit and friends — it'd away with quite
a lot of the pain of, e.g., not having a native struct-y
AttributedString.
Cheers!
Zachary Waldowski
zach@waldowski.me
On Tue, May 10, 2016, at 12:37 PM, Jordan Rose via swift-evolution >>> wrote:
One particular concern we've had is that many NSRanges aren’t
Range<Int>; they’re Range<String.UTF16Index>. I suppose things
wouldn’t get any *worse* there, though.
Jordan
On May 10, 2016, at 00:14, David Hart via swift-evolution <swift- >>>>> evolution@swift.org> wrote:
But it’s reasonably implementable? I guess the answer is yes if
you have already faced the same bridging concerns with
NSArray/Array. I’de really like this going forward, but I don’t
know how confident I am in writing a proposal.
On 10 May 2016, at 08:29, Douglas Gregor <dgregor@apple.com> >>>>>> wrote:
On May 9, 2016, at 11:23 PM, David Hart <david@hartbit.com> >>>>>>> wrote:
Why wouldn't it completely eliminate NSRange?
Because NSRange has a different representation than Range<Int>
(start+length vs. start/end), a pointer-to-NSRange has to come in
as Unsafe(Mutable)Pointer<NSRange> rather than
Unsafe(Mutable)Pointer<Range<Int>>. It’s the same reason that
(e.g.), an NSArray** parameter comes in as
UnsafeMutablePointer<NSArray> rather than
UnsafeMutablePointer<[AnyObject]>.
Are you thinking of NSNotFound? Could we migrate those APIs to
return an Optional Range<Int>?
If you had annotations on the APIs to say that they use
NSNotFound as a sentinel, yes.
- Doug
On 10 May 2016, at 05:49, Douglas Gregor <dgregor@apple.com> >>>>>>>> wrote:
On May 8, 2016, at 2:10 PM, David Hart via swift-evolution <swift- >>>>>>>>> evolution@swift.org> wrote:
Hello Swift-Evolution,
I spent some time coding on Linux with Swift 3 (latest
developement snapshot) and corelibs-foundation and I’ve hit
one major hurdle: passing and converting NSRange and Range
around between the different stdlib and Foundation APIs -
specifically in regards to String.
Is there a plan to simplify those pain points by converting
all corelibs-foundation APIs to accept/return Range on String
instead of NSRange? In that case, can’t we get rid of NSRange
completely?
One idea that had come up before was to bridge NSRange to
Range<Int>, although it wouldn’t completely eliminate NSRange
because the two types are not representationally identical.
That’s correct, but how would you make the String.UTF16Index values without the reference String? They’re not (guaranteed to be) integers.
Jordan
···
On May 10, 2016, at 16:04, Zach Waldowski <zach@waldowski.me> wrote:
Right, I 100% get it. :) This is a difficult problem space, and I'm sure you folks are aware that that difficulty is also reflected in how brutal it is to use all of these derivative string-range-based things in Swift right now. In this case, having no answer to this problem is worse than not having the API at all — check Stack Overflow or GitHub for how often a "just paste this in" String.Index.init(_: Int) comes up.
As far as NSTextCheckingResult goes, its ranges are always in the "indices" always in the space of the original string… do I have that right? So it would be programmer error to use those ranges in the wrong string just like it is with any Range<String.UTF16Index> today.
Zach Waldowski
On Tue, May 10, 2016, at 06:51 PM, Jordan Rose wrote:
By the way, this doesn’t mean it can’t be done, or that we can’t decide on some kind of partial solution! It just means that it needs to be carefully considered and explicitly addressed.
Jordan
On May 10, 2016, at 15:49, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:
We thought about that too. The problem is that it’s not always obvious what NSString or NSAttributedString the indexes refer to. For example, most of the NSRegularExpression APIs produce matches in the form of NSTextCheckingResult, which then doesn’t have a reference to the original string.
Jordan
On May 10, 2016, at 13:43, Zach Waldowski via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Would it be feasible to annotate those and have them appropriately converted to Range<String.UTF16Index> upon crossing the bridge? Thinking in particular of TextKit and friends — it'd away with quite a lot of the pain of, e.g., not having a native struct-y AttributedString.
On Tue, May 10, 2016, at 12:37 PM, Jordan Rose via swift-evolution wrote:
One particular concern we've had is that many NSRanges aren’t Range<Int>; they’re Range<String.UTF16Index>. I suppose things wouldn’t get any worse there, though.
Jordan
On May 10, 2016, at 00:14, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
But it’s reasonably implementable? I guess the answer is yes if you have already faced the same bridging concerns with NSArray/Array. I’de really like this going forward, but I don’t know how confident I am in writing a proposal.
On 10 May 2016, at 08:29, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:
On May 9, 2016, at 11:23 PM, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:
Why wouldn't it completely eliminate NSRange?
Because NSRange has a different representation than Range<Int> (start+length vs. start/end), a pointer-to-NSRange has to come in as Unsafe(Mutable)Pointer<NSRange> rather than Unsafe(Mutable)Pointer<Range<Int>>. It’s the same reason that (e.g.), an NSArray** parameter comes in as UnsafeMutablePointer<NSArray> rather than UnsafeMutablePointer<[AnyObject]>.
Are you thinking of NSNotFound? Could we migrate those APIs to return an Optional Range<Int>?
If you had annotations on the APIs to say that they use NSNotFound as a sentinel, yes.
- Doug
On 10 May 2016, at 05:49, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:
On May 8, 2016, at 2:10 PM, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Hello Swift-Evolution,
I spent some time coding on Linux with Swift 3 (latest developement snapshot) and corelibs-foundation and I’ve hit one major hurdle: passing and converting NSRange and Range around between the different stdlib and Foundation APIs - specifically in regards to String.
Is there a plan to simplify those pain points by converting all corelibs-foundation APIs to accept/return Range on String instead of NSRange? In that case, can’t we get rid of NSRange completely?
One idea that had come up before was to bridge NSRange to Range<Int>, although it wouldn’t completely eliminate NSRange because the two types are not representationally identical.
On Wed, May 11, 2016, at 01:13 PM, Jordan Rose wrote:
That’s correct, but how would you *make* the String.UTF16Index values
without the reference String? They’re not (guaranteed to be) integers.
Jordan
On May 10, 2016, at 16:04, Zach Waldowski <zach@waldowski.me> wrote:
Right, I 100% get it. :) This is a difficult problem space, and I'm
sure you folks are aware that that difficulty is also reflected in
how brutal it is to use all of these derivative string-range-based
things in Swift right now. In this case, having no answer to this
problem is worse than not having the API at all — check Stack
Overflow or GitHub for how often a "just paste this in"
String.Index.init(_: Int) comes up.
As far as NSTextCheckingResult goes, its ranges are always in the
"indices" always in the space of the original string… do I have that
right? So it would be programmer error to use those ranges in the
wrong string just like it is with any Range<String.UTF16Index> today.
Zach Waldowski
On Tue, May 10, 2016, at 06:51 PM, Jordan Rose wrote:
By the way, this doesn’t mean it can’t be done, or that we can’t
decide on some kind of partial solution! It just means that it needs
to be carefully considered and explicitly addressed.
Jordan
On May 10, 2016, at 15:49, Jordan Rose <jordan_rose@apple.com> >>>> wrote:
We thought about that too. The problem is that it’s not always
obvious what NSString or NSAttributedString the indexes refer to.
For example, most of the NSRegularExpression APIs produce matches
in the form of NSTextCheckingResult, which then doesn’t have a
reference to the original string.
Jordan
On May 10, 2016, at 13:43, Zach Waldowski via swift-evolution <swift- >>>>> evolution@swift.org> wrote:
Would it be feasible to annotate those and have them appropriately
converted to Range<String.UTF16Index> upon crossing the bridge?
Thinking in particular of TextKit and friends — it'd away with
quite a lot of the pain of, e.g., not having a native struct-y
AttributedString.
Cheers!
Zachary Waldowski
zach@waldowski.me
On Tue, May 10, 2016, at 12:37 PM, Jordan Rose via swift-evolution >>>>> wrote:
One particular concern we've had is that many NSRanges aren’t
Range<Int>; they’re Range<String.UTF16Index>. I suppose things
wouldn’t get any *worse* there, though.
Jordan
On May 10, 2016, at 00:14, David Hart via swift-evolution <swift- >>>>>>> evolution@swift.org> wrote:
But it’s reasonably implementable? I guess the answer is yes if
you have already faced the same bridging concerns with
NSArray/Array. I’de really like this going forward, but I don’t
know how confident I am in writing a proposal.
On 10 May 2016, at 08:29, Douglas Gregor <dgregor@apple.com> >>>>>>>> wrote:
On May 9, 2016, at 11:23 PM, David Hart <david@hartbit.com> >>>>>>>>> wrote:
Why wouldn't it completely eliminate NSRange?
Because NSRange has a different representation than Range<Int>
(start+length vs. start/end), a pointer-to-NSRange has to come
in as Unsafe(Mutable)Pointer<NSRange> rather than
Unsafe(Mutable)Pointer<Range<Int>>. It’s the same reason that
(e.g.), an NSArray** parameter comes in as
UnsafeMutablePointer<NSArray> rather than
UnsafeMutablePointer<[AnyObject]>.
Are you thinking of NSNotFound? Could we migrate those APIs to
return an Optional Range<Int>?
If you had annotations on the APIs to say that they use
NSNotFound as a sentinel, yes.
- Doug
On 10 May 2016, at 05:49, Douglas Gregor <dgregor@apple.com> >>>>>>>>>> wrote:
On May 8, 2016, at 2:10 PM, David Hart via swift-evolution >>>>>>>>>>> <swift-evolution@swift.org> wrote:
Hello Swift-Evolution,
I spent some time coding on Linux with Swift 3 (latest
developement snapshot) and corelibs-foundation and I’ve hit
one major hurdle: passing and converting NSRange and Range
around between the different stdlib and Foundation APIs -
specifically in regards to String.
Is there a plan to simplify those pain points by converting
all corelibs-foundation APIs to accept/return Range on
String instead of NSRange? In that case, can’t we get rid of
NSRange completely?
One idea that had come up before was to bridge NSRange to
Range<Int>, although it wouldn’t completely eliminate NSRange
because the two types are not representationally identical.
On Wed, May 11, 2016, at 01:13 PM, Jordan Rose wrote:
That’s correct, but how would you make the String.UTF16Index values without the reference String? They’re not (guaranteed to be) integers.
Jordan
On May 10, 2016, at 16:04, Zach Waldowski <zach@waldowski.me <mailto:zach@waldowski.me>> wrote:
Right, I 100% get it. :) This is a difficult problem space, and I'm sure you folks are aware that that difficulty is also reflected in how brutal it is to use all of these derivative string-range-based things in Swift right now. In this case, having no answer to this problem is worse than not having the API at all — check Stack Overflow or GitHub for how often a "just paste this in" String.Index.init(_: Int) comes up.
As far as NSTextCheckingResult goes, its ranges are always in the "indices" always in the space of the original string… do I have that right? So it would be programmer error to use those ranges in the wrong string just like it is with any Range<String.UTF16Index> today.
Zach Waldowski
On Tue, May 10, 2016, at 06:51 PM, Jordan Rose wrote:
By the way, this doesn’t mean it can’t be done, or that we can’t decide on some kind of partial solution! It just means that it needs to be carefully considered and explicitly addressed.
Jordan
On May 10, 2016, at 15:49, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:
We thought about that too. The problem is that it’s not always obvious what NSString or NSAttributedString the indexes refer to. For example, most of the NSRegularExpression APIs produce matches in the form of NSTextCheckingResult, which then doesn’t have a reference to the original string.
Jordan
On May 10, 2016, at 13:43, Zach Waldowski via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Would it be feasible to annotate those and have them appropriately converted to Range<String.UTF16Index> upon crossing the bridge? Thinking in particular of TextKit and friends — it'd away with quite a lot of the pain of, e.g., not having a native struct-y AttributedString.
On Tue, May 10, 2016, at 12:37 PM, Jordan Rose via swift-evolution wrote:
One particular concern we've had is that many NSRanges aren’t Range<Int>; they’re Range<String.UTF16Index>. I suppose things wouldn’t get any worse there, though.
Jordan
On May 10, 2016, at 00:14, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
But it’s reasonably implementable? I guess the answer is yes if you have already faced the same bridging concerns with NSArray/Array. I’de really like this going forward, but I don’t know how confident I am in writing a proposal.
On 10 May 2016, at 08:29, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:
On May 9, 2016, at 11:23 PM, David Hart <david@hartbit.com <mailto:david@hartbit.com>> wrote:
Why wouldn't it completely eliminate NSRange?
Because NSRange has a different representation than Range<Int> (start+length vs. start/end), a pointer-to-NSRange has to come in as Unsafe(Mutable)Pointer<NSRange> rather than Unsafe(Mutable)Pointer<Range<Int>>. It’s the same reason that (e.g.), an NSArray** parameter comes in as UnsafeMutablePointer<NSArray> rather than UnsafeMutablePointer<[AnyObject]>.
Are you thinking of NSNotFound? Could we migrate those APIs to return an Optional Range<Int>?
If you had annotations on the APIs to say that they use NSNotFound as a sentinel, yes.
- Doug
On 10 May 2016, at 05:49, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:
On May 8, 2016, at 2:10 PM, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Hello Swift-Evolution,
I spent some time coding on Linux with Swift 3 (latest developement snapshot) and corelibs-foundation and I’ve hit one major hurdle: passing and converting NSRange and Range around between the different stdlib and Foundation APIs - specifically in regards to String.
Is there a plan to simplify those pain points by converting all corelibs-foundation APIs to accept/return Range on String instead of NSRange? In that case, can’t we get rid of NSRange completely?
One idea that had come up before was to bridge NSRange to Range<Int>, although it wouldn’t completely eliminate NSRange because the two types are not representationally identical.
That makes sense. However, wouldn't this still be workable in terms
of bridging? If UTF16Index had an alternate representation for Swift-
side UTF-8 storage, that wouldn't ever come up for roundtripping
across the bridge. The offsets that come back from Foundation would
always be "UTF-16 indices how NSString understands it", which Swift
would necessarily understand because it implements -characterAtIndex:
for the bridge wrapper.
Zach
···
On Wed, May 11, 2016, at 01:19 PM, Jordan Rose wrote:
I’m not sure we’re going to stick to that in the future. It’s possible
we’ll want String to support UTF-8 buffers as well.
Jordan
On May 11, 2016, at 10:15, Zach Waldowski <zach@waldowski.me> wrote:
On Wed, May 11, 2016, at 01:13 PM, Jordan Rose wrote:
That’s correct, but how would you *make* the String.UTF16Index
values without the reference String? They’re not (guaranteed to be)
integers.
Jordan
On May 10, 2016, at 16:04, Zach Waldowski <zach@waldowski.me> >>>> wrote:
Right, I 100% get it. :) This is a difficult problem space, and I'm
sure you folks are aware that that difficulty is also reflected in
how brutal it is to use all of these derivative string-range-based
things in Swift right now. In this case, having no answer to this
problem is worse than not having the API at all — check Stack
Overflow or GitHub for how often a "just paste this in"
String.Index.init(_: Int) comes up.
As far as NSTextCheckingResult goes, its ranges are always in the
"indices" always in the space of the original string… do I have
that right? So it would be programmer error to use those ranges in
the wrong string just like it is with any Range<String.UTF16Index>
today.
Zach Waldowski
On Tue, May 10, 2016, at 06:51 PM, Jordan Rose wrote:
By the way, this doesn’t mean it can’t be done, or that we can’t
decide on some kind of partial solution! It just means that it
needs to be carefully considered and explicitly addressed.
Jordan
On May 10, 2016, at 15:49, Jordan Rose <jordan_rose@apple.com> >>>>>> wrote:
We thought about that too. The problem is that it’s not always
obvious what NSString or NSAttributedString the indexes refer to.
For example, most of the NSRegularExpression APIs produce matches
in the form of NSTextCheckingResult, which then doesn’t have a
reference to the original string.
Jordan
On May 10, 2016, at 13:43, Zach Waldowski via swift-evolution >>>>>>> <swift-evolution@swift.org> wrote:
Would it be feasible to annotate those and have them
appropriately converted to Range<String.UTF16Index> upon
crossing the bridge? Thinking in particular of TextKit and
friends — it'd away with quite a lot of the pain of, e.g., not
having a native struct-y AttributedString.
Cheers!
Zachary Waldowski
zach@waldowski.me
On Tue, May 10, 2016, at 12:37 PM, Jordan Rose via swift- >>>>>>> evolution wrote:
One particular concern we've had is that many NSRanges aren’t
Range<Int>; they’re Range<String.UTF16Index>. I suppose things
wouldn’t get any *worse* there, though.
Jordan
On May 10, 2016, at 00:14, David Hart via swift-evolution <swift- >>>>>>>>> evolution@swift.org> wrote:
But it’s reasonably implementable? I guess the answer is yes
if you have already faced the same bridging concerns with
NSArray/Array. I’de really like this going forward, but I
don’t know how confident I am in writing a proposal.
On 10 May 2016, at 08:29, Douglas Gregor <dgregor@apple.com> >>>>>>>>>> wrote:
On May 9, 2016, at 11:23 PM, David Hart <david@hartbit.com> >>>>>>>>>>> wrote:
Why wouldn't it completely eliminate NSRange?
Because NSRange has a different representation than
Range<Int> (start+length vs. start/end), a pointer-to-NSRange
has to come in as Unsafe(Mutable)Pointer<NSRange> rather than
Unsafe(Mutable)Pointer<Range<Int>>. It’s the same reason that
(e.g.), an NSArray** parameter comes in as
UnsafeMutablePointer<NSArray> rather than
UnsafeMutablePointer<[AnyObject]>.
Are you thinking of NSNotFound? Could we migrate those APIs
to return an Optional Range<Int>?
If you had annotations on the APIs to say that they use
NSNotFound as a sentinel, yes.
- Doug
On 10 May 2016, at 05:49, Douglas Gregor >>>>>>>>>>>> <dgregor@apple.com> wrote:
On May 8, 2016, at 2:10 PM, David Hart via swift-evolution >>>>>>>>>>>>> <swift-evolution@swift.org> wrote:
Hello Swift-Evolution,
I spent some time coding on Linux with Swift 3 (latest
developement snapshot) and corelibs-foundation and I’ve
hit one major hurdle: passing and converting NSRange and
Range around between the different stdlib and Foundation
APIs - specifically in regards to String.
Is there a plan to simplify those pain points by
converting all corelibs-foundation APIs to accept/return
Range on String instead of NSRange? In that case, can’t we
get rid of NSRange completely?
One idea that had come up before was to bridge NSRange to
Range<Int>, although it wouldn’t completely eliminate
NSRange because the two types are not representationally
identical.