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@swift.org> a écrit :
This is my draft proposal.
https://github.com/jcampbell05/swift-evolution/blob/master/proposals/0045-remove-falliable-initilizer.md
Let me know your thoughts.