[swift-evolution] Remove Failable Initializers

Gwendal Roué gwendal.roue at gmail.com
Mon Mar 7 13:04:12 CST 2016


I like the alternative, which makes it clear, at the call site, that the initializer is failable:
> An alternative is to change the falliable initiliser to have the optional symbol required at the call-site:
> 
> MyModel?()

Here is a rationale: imagine you have a type with a failable initializer AND a function that takes an optional value of this type, with default nil:

protocol P { }
struct Value {
    init(_ array:[P?]) { … }
    init?(_ nsarray: NSArray) { … }
}
func function(value: Value? = nil) { … }

The problem is that when the failable initializer fails, the function may not behave as expected:

let array: NSArray = …
function(Value(array)) // May not do what is expected

With the proposed alternative, the Swift compiler would force the code to read:

let array: NSArray = …
function(Value?(array)) // Now this is clearly bad. We need a value.

And the user is more likely to turn it into the correct code:

let array: NSArray = …
guard let value = Value(array) else {
    // process problem
}
function(value)


With the current state of Swift, how could the code above be fixed? By "fixed" I mean that it’s impossible for the user to trigger the default function value without knowing it:

1. Don’t use nil as a sentinel for the default value, and split the function in two variants:

protocol P { }
struct Value {
    init(_ array:[P?]) { … }
    init?(_ nsarray: NSArray) { … }
}
func function() { … }
func function(value: Value) { … }

let array: NSArray = …
function(Value(array)) // OK: does not compile

It works, BUT it may lead to an API explosion.

2. Don’t use nil as a sentinel for the default value, and use a special sentinel value instead:

protocol P { }
struct Value {
    static var DefaultValue: Value = ...
    init(_ array:[P?]) { }
    init?(_ nsarray: NSArray) { }
}
func function(value: Value = Value.DefaultValue) { }

let array: NSArray = …
function(Value(array)) // OK: does not compile

It works, BUT not all types can easily lock a value for such a purpose. Plus it’s a very uncommon pattern.

I don’t see any other way to fix the problem.

So I would quite welcome the alternative proposed by James Campbell.

Gwendal


> Le 7 mars 2016 à 16:40, James Campbell via swift-evolution <swift-evolution at swift.org> a écrit :
> 
> This is my draft proposal.
> 
> https://github.com/jcampbell05/swift-evolution/blob/master/proposals/0045-remove-falliable-initilizer.md <https://github.com/jcampbell05/swift-evolution/blob/master/proposals/0045-remove-falliable-initilizer.md>
> 
> Let me know your thoughts.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160307/b576a12d/attachment.html>


More information about the swift-evolution mailing list