[swift-evolution] [Proposal] Remove force unwrapping in function signature.
Vladimir.S
svabox at gmail.com
Wed Jun 29 06:40:48 CDT 2016
On 29.06.2016 6:57, Chris Lattner via swift-evolution wrote:
>
>> On Jun 27, 2016, at 4:42 PM, Saagar Jha via swift-evolution
>> <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>
>> Alright, I’ve written it up a proposal; you can find it here
>> <https://gist.github.com/saagarjha/f33fecd4576f40133b6469da942ef453>.
>> This is my first proposal (and anyways I’ve been told that I can be
>> unclear), so if you guys see anything that should be changed feel free to
>> let me know. Here it is inline:
>>
> Hi Saagar,
>
> If I understand your proposal correctly, you are suggesting that we remove
> T! and just force people to use T? or T. This is a commonly rejected
As I understand, Saagar suggests to disallow T! for function parameters
only. And allow only T or T?.
About the API, as I understand, the suggestion is to explicitly use guard:
func someAPIFunc(t: T?) {
guard let t = t else { fatalError("t==nil was not expected in
someAPIFunc") }
// code of function
print(t) // `t` is not optional here
}
From one side this adds more boilerplate code for API functions, but from
other - such function is very clear about the behavior in case of `nil`
sent to such function. I.e. all is explicit and clear. With IUO it is not
obvious what will be the behavior if `nil` will be sent to func.
Personally I'm not sure if I'm +1 for this suggestion or -1.. Probably +1
because of more obvious behavior and the fact that we can have more
descriptive error in case of `nil` in such function.
> proposal (though not on the list yet) that frequently comes up. The
> problem with your proposal is that you don’t provide any solutions to the
> problems that T! is currently solving: that of two-phase initialization and
> importing of APIs that have not been nullability audited. It isn’t
> pragmatic to handle these cases as T?
>
> -Chris
>
>>
>> Remove implicitly unwrapped optionals as function parameters
>>
>> * Proposal: SE-NNNN
>> <x-msg://38/NNNN-remove-implicitly-unwrapped-function-parameters.md>
>> * Author: Swift Developer <https://github.com/swiftdev>
>> * Status: *Awaiting review*
>> * Review manager: TBD
>>
>>
>> Introduction
>>
>> Swift, in contrast with Objective-C, makes a distinction between values
>> that may be |nil| and values that can never be |nil| through its use of
>> Optionals. Due to the fact that Objective-C does not make this
>> distinction, Objective-C functions that do not use the Nullability
>> <https://developer.apple.com/swift/blog/?id=25> annotations are imported
>> with parameters of the implicitly unwrapped optional type. Unfortunately,
>> this allows users to write their own Swift code that looks like this:
>>
>> |func foo(bar: Int!) { //… } |
>>
>> Due to the confusion this may cause, we would like to propose the
>> *removal of implicitly unwrapped optionals as function parameters*.
>> Discussion on this topic may be found here
>> <http://article.gmane.org/gmane.comp.lang.swift.evolution/21730/>.
>>
>>
>> Motivation
>>
>> Implicitly unwrapped optionals are currently allowed in function
>> declarations. Consider the following function:
>>
>> |func triple(forceUnwrapping aNumber: Int) -> Int { return aNumber * 3 }
>> let possiblyNil = Int("foo") triple(forceUnwrapping: possiblyNil) |
>>
>> |possiblyNil| is an |Int?|; thus, this example will not compile due to
>> |triple(forceUnwrapping:)| expecting an |Int|. It is easy to imagine a
>> Swift beginner writing code that looks like this to "fix" the problem:
>>
>> |func triple(forceUnwrapping aNumber: Int!) -> Int { return aNumber * 3 }
>> let possiblyNil = Int("foo") triple(forceUnwrapping: possiblyNil) |
>>
>> While this version compiles, it crashes due to the force unwrapping of a
>> |nil| value. Unfortunately, the compiler "hides" this fact by making it
>> seem like it's acceptable to pass in |nil|–it doesn't make the forced
>> unwrapping *explicit*.
>>
>>
>> Proposed solution
>>
>> The safest solution, in this case, is to prevent the use of implicitly
>> unrwapped optionals in function signatures. By forcing users to write
>>
>> |func triple(forceUnwrapping aNumber: Int) -> Int { return aNumber * 3 } |
>>
>> or
>>
>> |func triple(forceUnwrapping aNumber: Int?) -> Int { return aNumber * 3 } |
>>
>> the compiler will complain, reminding users that they should probably
>> attempt to safely unwrap the optional before using it.
>>
>>
>> Detailed design
>>
>> The proposal will prevent the use of implicitly unwrapped optionals in
>> function signatures for both Swift code as well as imported Objective-C
>> code. As non-annotated Objective-C functions are currently imported as
>> implicitly unwrapped, they will be converted to optionals as a
>> preliminary step. Non-audited frameworks can be audited in the future so
>> that they can be tagged with |_Nonnull| if necessary.
>>
>>
>> Impact on existing code
>>
>> This is a proposal is a source breaking change, but it should be easily
>> mitigated using a migrator. Existing functions with implicitly unwrapped
>> optionals can be changed to optional; users can easily shadow variables
>> with a |guard| or change their function to non-optional.
>>
>>
>> Alternatives considered
>>
>>
>> Importing Objective-C functions as-is, but disallowing implictly
>> unwrapped optionals in Swift code
>>
>> This reduces the burden on existing frameworks and adding Nullability
>> annotations, but creates a sort of disconnect between Objective-C and
>> Swift in that it prevents Swift developers from writing functions with
>> implicitly unwrapped optionals.
>>
>>
>> Doing nothing
>>
>> Obviously, this has the benefit of keeping the current behavior and not
>> requiring a migrator. However, I believe that the unsafe behavior that
>> this encourages is not worth keeping.
>>
>>
>>
>> On Mon, Jun 27, 2016 at 1:35 PM Dennis Lysenko
>> <dennis.s.lysenko at gmail.com <mailto:dennis.s.lysenko at gmail.com>> wrote:
>>
>> +1. This is sort of how Kotlin does it. In Kotlin, IUOs are strictly
>> a carryover from Java. They show up in method signatures from
>> non-nullable-annotated Java, but you can't define a new method that
>> takes e.g. an Int!.
>>
>> The limited scope of this proposal is ideal in my opinion since we
>> see areas where IUOs are clearly useful (ViewControllers for
>> instance) but defining new functions that take implicitly unwrapped
>> optionals makes no sense. If you need to pass a IUO at the call site,
>> you can define the function taking a non-optional value and pass the
>> IUO to that. There is no use case I can think of for having it in
>> method/function signatures.
>>
>> RE: language inconsistencies, there is no such issue in practice in
>> Kotlin where there is also inconsistency in the same vein. I see it
>> simply as a compromise that achieves the goal of keeping a useful
>> feature but discouraging its overuse by forbidding its use in places
>> where its use could confuse and snowball down the line into teaching
>> developers worse code quality.
>>
>> On Mon, Jun 27, 2016 at 12:04 PM Charlie Monroe via swift-evolution
>> <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>
>> Ok, I see - though I find myself using occasionally IUOs in Swift
>> as well - e.g. when you can't use the default values because they
>> depend on self, etc.
>>
>> Eliminating it just from method signatures IMHO brings an
>> incosistency into the language. Why would you eliminate it only
>> from method signatures - this proposal mentioned importing ObjC
>> API in the beginning - why not then mark those properties all as
>> optional as well? IUOs are scheduled to be removed completely
>> once the language reaches a point where it can handle most
>> scenarios otherwise...
>>
>> Try to imagine some APIs brought to Swift with default being
>> nullable:
>>
>> /// Imported from
>> publicclassNSOrderedSet : NSObject, NSCopying, NSMutableCopying,
>> NSSecureCoding, NSFastEnumeration{
>>
>> publicvarcount: Int{ get }
>> publicfuncobjectAtIndex(idx: Int) -> AnyObject?
>> publicfuncindexOfObject(object: AnyObject?) -> Int
>> publicinit()
>> publicinit(objects: UnsafePointer<AnyObject?>, count cnt: Int)
>> publicinit?(coder aDecoder: NSCoder?)
>> }
>>
>> This doesn't make much sense - mostly objectAtIndex(_:).
>>
>>> On Jun 27, 2016, at 8:35 PM, Saagar Jha <saagarjha28 at gmail.com
>>> <mailto:saagarjha28 at gmail.com>> wrote:
>>>
>>> I think you’re mistaking the scope of the proposal. It’s simply
>>> removing IUOs in /function signatures/, not throughout the language.
>>>
>>> On Mon, Jun 27, 2016 at 11:31 AM Charlie Monroe via
>>> swift-evolution <swift-evolution at swift.org
>>> <mailto:swift-evolution at swift.org>> wrote:
>>>
>>> There are many useful cases for IUO in Swift - mostly when
>>> you have variables that cannot be calculated at the point of
>>> calling super.init(), but are guaranteed to be filled during
>>> initialization - i.e. during the lifetime of the object, the
>>> value is nonnil, but may be nil for a short period of time.
>>>
>>> Or @IBOutlets. Making all @IBOutlets optionals would make
>>> the code either riddled with ! or shadowed locally
>>> re-declared instance members.
>>>
>>>
>>> > On Jun 27, 2016, at 8:12 PM, Jean-Daniel Dupas
>>> <mailing at xenonium.com <mailto:mailing at xenonium.com>> wrote:
>>> >
>>> > Maybe we can prohibit it in Swift function declaration,
>>> and allow it only when importing native code.
>>> >
>>> > As David, I don’t see any compelling reason to allow such
>>> construct in Swift.
>>> >
>>> >> Le 27 juin 2016 à 10:39, Charlie Monroe via
>>> swift-evolution <swift-evolution at swift.org
>>> <mailto:swift-evolution at swift.org>> a écrit :
>>> >>
>>> >> When you import ObjC code that has no nullability
>>> annotation, IUO make sense since:
>>> >>
>>> >> - they can be checked against nil
>>> >> - typically, most values in APIs are nonnull (looking at
>>> Foundation, for example, which is why Apple has the
>>> NS_ASSUME_NONNULL_BEGIN to mark entire regions as nonnull,
>>> yet there is no NS_ASSUME_NULL_BEGIN)
>>> >>
>>> >> Importing them as optionals would make it really hard to
>>> work with the code - whenever you get a value, it's an
>>> optional, even in cases where it makes no sense and adding !
>>> to unwrap the optional is not a great solution. And the
>>> other solution is to use guards everywhere.
>>> >>
>>> >> IMHO the IUO is a nice (temporary) solution for using
>>> un-annotated code until it is. But the "pressure" should be
>>> applied on the ObjC code.
>>> >>
>>> >>> On Jun 27, 2016, at 10:03 AM, David Rönnqvist
>>> <david.ronnqvist at gmail.com
>>> <mailto:david.ronnqvist at gmail.com>> wrote:
>>> >>>
>>> >>> I don’t know about the chances of getting approved, but
>>> I think this is something worth discussing.
>>> >>>
>>> >>> It might just be my ignorance, but I can’t think of a
>>> good reason why a function argument would be force
>>> unwrapped. Either it’s non-null and the caller is expected
>>> to unwrap it or it’s nullable and the method is expected to
>>> handle the nil value. So I’m positive to that part of the
>>> proposal.
>>> >>>
>>> >>> As to what we should do with the generated interfaces of
>>> Objective-C code that hasn’t been annotated with
>>> nullability, I think that needs input from more people to
>>> find the preferred solution.
>>> >>>
>>> >>> Once that’s been discussed some more, I’d be willing to
>>> write up a formal proposal if you don’t feel like it
>>> (assuming the discussion leads somewhere).
>>> >>>
>>> >>> - David
>>> >>>
>>> >>>
>>> >>>> On 27 Jun 2016, at 06:28, Charlie Monroe via
>>> swift-evolution <swift-evolution at swift.org
>>> <mailto:swift-evolution at swift.org>> wrote:
>>> >>>>
>>> >>>> See
>>> https://github.com/apple/swift-evolution/blob/master/process.md
>>> - you would need to make an official proposal and submit it
>>> as pull request. But given the reaction here, it's unlikely
>>> to get approved.
>>> >>>>
>>> >>>> Also, the ObjC code without nullability is getting
>>> fairly rare - all Apple's frameworks are with nullability
>>> information (as far as I've checked) in macOS 10.12, iOS 10.
>>> Third party libraries should be updated to use nullability
>>> (and most libraries that are maintained already do).
>>> >>>>
>>> >>>>
>>> >>>>> On Jun 25, 2016, at 5:13 PM, Spromicky via
>>> swift-evolution <swift-evolution at swift.org
>>> <mailto:swift-evolution at swift.org>> wrote:
>>> >>>>>
>>> >>>>> So, its proposal is dead, or what we must to do to
>>> force it to swift-evolution repo on GitHub?
>>> >>>>>
>>> >>>>>> Hello, everyone!
>>> >>>>>>
>>> >>>>>> I wanna propose to you to remove force unwrapping in
>>> fuction signature for swift code. That no sense in clear
>>> swift code. If we wanna use some optional value as function
>>> param, that is not optional, we must unwrap it before
>>> function call.
>>> >>>>>> People who new in swift look at how they old Obj-C
>>> code (without nullability modifiers) translate in to swift:
>>> >>>>>>
>>> >>>>>> Obj-C:
>>> >>>>>> - (void)foo:(NSInteger)bar {
>>> >>>>>> //...
>>> >>>>>> }
>>> >>>>>>
>>> >>>>>> Swift transaliton:
>>> >>>>>> func foo(bar: Int!) {
>>> >>>>>> //...
>>> >>>>>> }
>>> >>>>>>
>>> >>>>>> And think that force unwrapping in signature is good
>>> practice. And start write functions in clear swift code like
>>> this:
>>> >>>>>>
>>> >>>>>> func newFoo(bar: Int!) {
>>> >>>>>> //...
>>> >>>>>> }
>>> >>>>>>
>>> >>>>>> and use it like this:
>>> >>>>>>
>>> >>>>>> let bar: Int? = 1
>>> >>>>>> newFoo(bar)
>>> >>>>>>
>>> >>>>>> And it really work, and they does not think that this
>>> can crash in case if `bar` will be `nil`.
>>> >>>>>> But in clear swift we wanna work with parametrs in
>>> function that clearly or optional, or not.
>>> >>>>>>
>>> >>>>>> func newFoo(bar: Int) {
>>> >>>>>> //...
>>> >>>>>> }
>>> >>>>>>
>>> >>>>>> or
>>> >>>>>>
>>> >>>>>> func newFoo(bar: Int?) {
>>> >>>>>> //...
>>> >>>>>> }
>>> >>>>>>
>>> >>>>>> When we write a new function we know what we need in
>>> this case and use optional params or not.
>>> >>>>>>
>>> >>>>>> So my proposal is remove force unwrapping(`!`) from
>>> function signatures, cause it have no sense, and that
>>> confuse new users.
>>> >>>>>>
>>> >>>>>>
>>> >>>>>>
>>> >>>>> _______________________________________________
>>> >>>>> swift-evolution mailing list
>>> >>>>> swift-evolution at swift.org
>>> <mailto:swift-evolution at swift.org>
>>> >>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> >>>>
>>> >>>> _______________________________________________
>>> >>>> swift-evolution mailing list
>>> >>>> swift-evolution at swift.org
>>> <mailto:swift-evolution at swift.org>
>>> >>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> >>>
>>> >>
>>> >> _______________________________________________
>>> >> swift-evolution mailing list
>>> >> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>> >> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> >
>>>
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>>> --
>>> -Saagar Jha
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>> --
>> -Saagar Jha
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
> _______________________________________________
> 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