Thanks for the feedback! I thought about nullability with type aliases too, and I think we could avoid some of the issues there with something like this:
- (ObjectType)objectAtIndex:(nonnull NSArrayIndex)index; The case where it’s a parameter to a method is easy—I’m not sure where the _Nonnull would go when there’s no pointer. Perhaps like this: NSArrayIndex _Nonnull foo = 42; As far as NSNull as a nullability specifier for arrays and other Objective-C collections, I think that’s fantastic! Like you said, I see this as another tool in the toolbox that helps make Objective-C more self-documenting, both to the developer and the compiler. Jeff Kelley [email protected] | @SlaunchaMan <https://twitter.com/SlaunchaMan> | jeffkelley.org On Tue, Feb 14, 2017 at 2:08 PM, Philippe Hausler <[email protected]> wrote: > The feature in this case I would claim is independent of the adopters. > Personally I think this would be a useful feature to allow for better > exposition into swift but also more robust objective-c APIs. > > Something to consider here is that not all NSUIntegers can be NSNotFound, > sometimes the return value is 0. It would be interesting to consider that > _Nullable would be parameterized via a constant expression. This is a straw > man refinement here (the exact spelling would be something we would have to > audit the way it is implemented and likely use macros to compose the right > nullability concepts) > > Lets take for example this API: > > + (NSInteger)writePropertyList:(id)plist toStream:(NSOutputStream > *)stream format:(NSPropertyListFormat)format options:( > NSPropertyListWriteOptions)opt error:(out NSError **)error; > > The return value here would be 0 if an error occurs. So the nullability > value would be 0. > > + (nullable(0) NSInteger)writePropertyList:(id)plist > toStream:(NSOutputStream *)stream format:(NSPropertyListFormat)format > options:(NSPropertyListWriteOptions)opt error:(out NSError **)error; > > But other APIs like you indicated: > > - (NSUInteger)indexOfObject:(ObjectType)anObject; > > Could be converted to: > > - (nullable(NSNotFound) NSUInteger)indexOfObject:(ObjectType)anObject; > > Which would immediately be an indication to the reader what the “null” > value would be represented as. Of course your concept of type aliases might > be a decent way to group concepts together but if lets say there was an > index type for NSArray; obviously you might want a index return value to be > nullable but it would be a bit confusing to take a nullable parameter into > certain APIs. > > Given a concept of NSArrayIndex as you suggested (that being nullable) > would have the problem that > > - (ObjectType)objectAtIndex:(NSUInteger)index; > > Would either incorrectly indicate it would be nullable or it would have a > different type. > > There would be other cases where structural types might need a nullable > placeholder value, e.g. NSRange with a location of NSNotFound and a length > of 0 (however that strictly isn’t correct since it is just the location > that indicates null-ness.. but that is probably more of an implementation > detail and should probably be corrected imho). > > There could also be cases where an API returns either an object of a > specific type or NSNull as a placeholder. This would be nice to be able to > express as a nullable type especially in generics. For example: > `NSArray<_Nullable(NSNull *) Foo *> *` could be a neat way to express > `Array<Foo?>` which cannot be expressed currently. > > Overall I think this could really reduce some of the overlays for all the > frameworks on Mac OS X and iOS, improve the expressivity of Objective-C > APIs, offer more accurate bridged representations, and generally give API > authors an opportunity to more correctly represent what should be exposed > in Swift without needing to write overlays that could easily have poor > interaction with things like subclassing or delegation. > > As a side note: I am not certain if the parameterization of nullability > annotations would even be possible in the current compiler implementations > or if it would be easier to use an attribute instead (that would be left to > implementation detail). > > I would guess that if this feature would be available it would take a > combined effort from all API maintainers to annotate their return values > and any un-annotated shouldn’t be exposed as a IOU since they have non nil > values already. Furthermore the timeframe to do so would probably be > independent of the implementation of this type of feature. > > Those caveats aside - I think it would be a fantastic tool in the toolbox! > > On Feb 14, 2017, at 10:41 AM, Jeff Kelley via swift-evolution < > [email protected]> wrote: > > On Mon, Feb 13, 2017 at 11:53 PM, Rod Brown <[email protected]> > wrote: > >> I think the biggest problem we're going to face with this one is changes >> to Objective-C are out of scope for Swift Evolution. Apple tend to be the >> ones in control of the development of new Objective-C features and >> compatibility because they control the compiler. >> > > I don’t think that Objective-C changes are out of bounds when Swift is > involved—see my past, accepted proposal at SE-0033 > <https://github.com/apple/swift-evolution/blob/master/proposals/0033-import-objc-constants.md> > . > > >> That said, as a request to Apple for this change, I think it's a >> reasonable idea for Ints, but I'm not sure of its feasibility for other >> types. Could the API be descriptive enough to cover enough types? (Eg >> CGRectNull) >> > > It’s an open-and-shut case for any standard primitive, but structs like > CGRect are where it starts to get tricky. I see that CGRect conforms to > Equatable when it’s imported into Swift; perhaps that could be enough for > this to work? If the translation to and from nil happens in the Swift > side, I can see Equatable as a reasonable requirement for the type. > > > >> On 14 Feb 2017, at 2:33 pm, Jeff Kelley via swift-evolution < >> [email protected]> wrote: >> >> Hi all, >> >> I don’t have a formal proposal written up yet, but in my continued quest >> to make better-annotated Objective-C code, I had an idea for bridging nil >> with primitives. Since in Objective-C we often use constant values to >> represent invalid values or nil, the most obvious being NSNotFound, >> could we use that as a shorthand for nil? Something like this for NSArray >> : >> >> - (NSUInteger NS_SWIFT_NIL(NSNotFound))index >> OfObject:(ObjectType)anObject; >> >> This is a little verbose, so it could also work with a typedef: >> >> typedef NSUInteger NS_SWIFT_NIL(NSNotFound) NSArrayIndex; >> - (NSArrayIndex)indexOfObject:(ObjectType)anObject; >> >> This would change the existing Swift interface to return an Int? instead >> of an Int. I see this as working both ways—converting these values to nil >> when returning from Objective-C to Swift, and sending these values instead >> of nil when Swift calls into Objective-C code. >> >> Is this worth writing up a proposal for? Is another, better method >> already in someone’s mind? >> >> >> Jeff Kelley >> >> [email protected] | @SlaunchaMan <https://twitter.com/SlaunchaMan> | >> jeffkelley.org >> >> > > > Jeff Kelley > > [email protected] | @SlaunchaMan <https://twitter.com/SlaunchaMan> | > jeffkelley.org > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution > > >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
