Remove Failable Initializers

Oh. I missed that. Thanks. Then I guess I could go either way. Keeping failable initializers, in that case, would be fine and makes sense.

···

Sent from my iPhone

On Mar 3, 2016, at 12:55 AM, Brent Royal-Gordon <brent@architechies.com> wrote:

I have found that failable initializers really don’t fit in well with Swift’s strict initialization rules (which I think are great). Every time I tried to use them I always had to make sacrifices with having an implicitly unwrapped optional or optional when I shouldn’t.

Are you talking about the "All stored properties of a class instance must be initialized before returning nil from an initializer" error? Because that's being fixed in Swift 2.2.

--
Brent Royal-Gordon
Architechies

The reasoning for me is that they help describe the difference between a function that can return a nil value as part of it's normal operation and a function that can encounter an unexpected error.

···

On 03 Mar 2016, at 00:44, Ross O'Brien via swift-evolution <swift-evolution@swift.org> wrote:

At the risk of appearing glib or naive - which isn't my intention, I'd like to know the answer - is there not a similar argument to be made for any function which returns an optional instead of throwing a more descriptive error? Asking an array for its first element returns an optional because of the possibility it might have no elements in it; should this throw an error instead of being 'failable'?

On Wed, Mar 2, 2016 at 11:35 PM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

On 2 Mar 2016, at 23:07, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Mar 2, 2016, at 1:11 PM, James Campbell via swift-evolution <swift-evolution@swift.org> wrote:

Given that we now have error handling and availability checks does it make sense to have Failable Initializers which date back to Swift 1.1?

Our error handling schema (https://github.com/apple/swift/blob/master/docs/ErrorHandlingRationale.rst#kinds-of-error\) defines how error conditions are handled, and one important class of them (e.g. the "string to int" case) is best modeled as returning an optional. This works really well in practice for functions/methods in general.

Could you give an example of why failable is the better fit here? To me the following two statements are identical:

  let a = FailableType()
  let b = try? ThrowableType()

Except that in the latter case the try? is more explicit about what is happening (and that it can fail), and I have the option of catching the error to find out more about what went wrong. With some optimisation it should be possible for try? to be just as efficient as a failable initialiser I think.

That said, the failable initialiser could have the same explicit call syntax if it required a trailing question-mark, e.g:

  let a = FailableType()?

As currently the only indicator is on the initialiser declaration itself. Still, when it comes to debugging I’ve found it very useful to force myself to use error handling instead, as it means I have to give reasons for why something failed, which can make it easier to track issues when they do arise.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Please expand your proposal to include a description of the how importing ObjC types to Swift works.

-Chris

···

On Mar 7, 2016, at 7:40 AM, James Campbell via swift-evolution <swift-evolution@swift.org> wrote:

This is my draft proposal.

https://github.com/jcampbell05/swift-evolution/blob/master/proposals/0045-remove-falliable-initilizer.md

Let me know your thoughts.

So we could try to bridge `init?` from objective-c so they become `init()
throws` but perhaps a less disruptive solution is to only allow `init?` for
swift classes that inherit from @objc ? I can't see how it is possible to
let `init throw` bridge back to objective-c cleanly.

I have updated my proposal to explore both of these options.

···

*___________________________________*

*James⎥Head of Trolls*

*james@supmenow.com <james@supmenow.com>⎥supmenow.com <http://supmenow.com>*

*Sup*

*Runway East *

*10 Finsbury Square*

*London*

* EC2A 1AF *

On Mon, Mar 7, 2016 at 6:25 PM, Chris Lattner <clattner@apple.com> wrote:

On Mar 7, 2016, at 7:40 AM, James Campbell via swift-evolution < > swift-evolution@swift.org> wrote:

This is my draft proposal.

https://github.com/jcampbell05/swift-evolution/blob/master/proposals/0045-remove-falliable-initilizer.md

Let me know your thoughts.

Please expand your proposal to include a description of the how importing
ObjC types to Swift works.

-Chris

You've spelled "failable" wrong (both in the proposal and its filename). Were you thinking of "fallible" -- capable of making mistakes or being wrong?

Also, the official definition of a "failable initializer" is written in:

<https://github.com/apple/swift/blob/master/docs/FailableInitializers.rst&gt;

It includes both optional return type and throwing initializers.

-- Ben

···

On 7 Mar 2016, at 15:40, James Campbell via swift-evolution <swift-evolution@swift.org> wrote:

This is my draft proposal.

https://github.com/jcampbell05/swift-evolution/blob/master/proposals/0045-remove-falliable-initilizer.md

Let me know your thoughts.

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.

Ehrm, correction:
If initializers were void-functions in every aspect, how would we explain
what happens here:
let a: Int = Int.init(123)
let b: Int? = Int.init("ff", radix: 16)
print(a) // 123
print(b) // Optional(255)
?

···

On Wed, Mar 9, 2016 at 12:41 PM, Jens Persson <jens@bitcycle.com> wrote:

> Swift, on the other hand, is different:
> Init-methods are void-functions in every aspect, with the irregularity
> that we can return "nil" (if the initializer is marked accordingly).

Initializers are clearly not void-functions, as they return a value of
type T.
And failable initializers return an Optional<T>.
Where T is the type to which the initializer belongs.

If initializers where void-functions in every aspect, how would we explain
what happens here:
let a: Int = Int.init(123)
let b: Int? = Int.init("ff", radix: 16)
print(a) // 123
print(b) // 255
?

/Jens

On Wed, Mar 9, 2016 at 11:32 AM, Tino Heth via swift-evolution < > swift-evolution@swift.org> wrote:

As ease of use and performance implications have been discussed, I would
still like to see the question of consistency addressed:
In Objective-C, returning nil from an initializer is nothing special — it
is a regular function that returns id (self in most cases).

Swift, on the other hand, is different:
Init-methods are void-functions in every aspect, with the irregularity
that we can return "nil" (if the initializer is marked accordingly).

Am I the only one who has the feeling that this is a little bit odd?
What kind of method is a initializer in Swift?

Tino

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
bitCycle AB | Smedjegatan 12 | 742 32 Östhammar | Sweden
http://www.bitcycle.com/
Phone: +46-73-753 24 62
E-mail: jens@bitcycle.com

--
bitCycle AB | Smedjegatan 12 | 742 32 Östhammar | Sweden

Phone: +46-73-753 24 62
E-mail: jens@bitcycle.com

Initializers are clearly not void-functions

Really?
There is no "return ..." in a regular init-method, and every other function declared like "init" won't return anything but void — so imho the "clearly" is more than questionable:
Just replace the magic name with anything else, and you have void function.

The error handdling model as described in
https://github.com/apple/swift/blob/master/docs/ErrorHandlingRationale.rst#kinds-of-error
is
very sensible and consistently applied throughout the language.

Returning an optional is a simplified form of returning an error when there
is only one straightforward way of failing. This is a very common case and
is simpler than using an error, for which you need to: 1) call
w/ try? 2) add 'throws' to the function 3) return some kind of error
instance of some type

···

On Thursday, 3 March 2016, David Hart via swift-evolution < swift-evolution@swift.org> wrote:

The reasoning for me is that they help describe the difference between a
function that can return a nil value as part of it's normal operation and a
function that can encounter an unexpected error.

On 03 Mar 2016, at 00:44, Ross O'Brien via swift-evolution < > swift-evolution@swift.org > <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:

At the risk of appearing glib or naive - which isn't my intention, I'd
like to know the answer - is there not a similar argument to be made for
any function which returns an optional instead of throwing a more
descriptive error? Asking an array for its first element returns an
optional because of the possibility it might have no elements in it; should
this throw an error instead of being 'failable'?

On Wed, Mar 2, 2016 at 11:35 PM, Haravikk via swift-evolution < > swift-evolution@swift.org > <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:

On 2 Mar 2016, at 23:07, Chris Lattner via swift-evolution < >> swift-evolution@swift.org >> <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:

On Mar 2, 2016, at 1:11 PM, James Campbell via swift-evolution < >> swift-evolution@swift.org >> <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:

Given that we now have error handling and availability checks does it
make sense to have Failable Initializers which date back to Swift 1.1?

Our error handling schema (
https://github.com/apple/swift/blob/master/docs/ErrorHandlingRationale.rst#kinds-of-error\)
defines how error conditions are handled, and one important class of them
(e.g. the "string to int" case) is best modeled as returning an optional.
This works really well in practice for functions/methods in general.

Could you give an example of why failable is the better fit here? To me
the following two statements are identical:

let a = FailableType()
let b = try? ThrowableType()

Except that in the latter case the try? is more explicit about what is
happening (and that it can fail), and I have the option of catching the
error to find out more about what went wrong. With some optimisation it
should be possible for try? to be just as efficient as a failable
initialiser I think.

That said, the failable initialiser could have the same explicit call
syntax if it required a trailing question-mark, e.g:

let a = FailableType()?

As currently the only indicator is on the initialiser declaration itself.
Still, when it comes to debugging I’ve found it very useful to force myself
to use error handling instead, as it means I have to give reasons for why
something failed, which can make it easier to track issues when they do
arise.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
<javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
<javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>
https://lists.swift.org/mailman/listinfo/swift-evolution

We prefer 'failable', which is a perfectly cromulent word, and one more accessible to non-English majors.

-Joe

···

On Mar 7, 2016, at 11:14 AM, Ben Rimmington via swift-evolution <swift-evolution@swift.org> wrote:

On 7 Mar 2016, at 15:40, James Campbell via swift-evolution <swift-evolution@swift.org> wrote:

This is my draft proposal.

https://github.com/jcampbell05/swift-evolution/blob/master/proposals/0045-remove-falliable-initilizer.md

Let me know your thoughts.

You've spelled "failable" wrong (both in the proposal and its filename). Were you thinking of "fallible" -- capable of making mistakes or being wrong?

Also, the official definition of a "failable initializer" is written in:

<https://github.com/apple/swift/blob/master/docs/FailableInitializers.rst&gt;

It includes both optional return type and throwing initializers.

I think we should not take over this thread with much more of this
discussion but eg this:
let i: Int = Int.init(123)
would not compile if that initializer had a return type of Void rather than
Int. The only initializer I can think of that returns Void is Void() /
Void.init().
/Jens

···

On Wed, Mar 9, 2016 at 2:15 PM, Tino Heth <2th@gmx.de> wrote:

Initializers are clearly not void-functions

Really?
There is no "return ..." in a regular init-method, and every other
function declared like "init" won't return anything but void — so imho the
"clearly" is more than questionable:
Just replace the magic name with anything else, and you have void function.

--
bitCycle AB | Smedjegatan 12 | 742 32 Östhammar | Sweden

Phone: +46-73-753 24 62
E-mail: jens@bitcycle.com

Error handling forces you to do something about the possibility of a failure.

So does using a failable initializer: the value is in an Optional, so you can't access it without either testing and unwrapping or just force-unwrapping. The type system, rather than the `try` requirement, is what forces you to handle the error, but it's the same idea.

···

--
Brent Royal-Gordon
Architechies

class Model {

let property: String
let property1: String
let property2: String
let property3: String

init?(json: [String: AnyObject]) throws {

property = try json.require("property")
property1 = try json.require("property1")
property2 = try json.require("property2")
property3 = try json.require("property3")

}

}

Require reads the key from the dict and tries to cast it to the same type as the variable its being assigned to and throws an error if this fails (like it doesn't exist or it can't be casted). This has much less boilerplate, its easier to read and also we can throw an error saying ("We couldn't parse property1").

You're right, that's an improvement over the failable initializer. *So make this a throwing init instead.* It's not like the existence of failable initializers keeps you from using `throws`.

Meanwhile, things like `Int.init(_: String)` and `NSImage.init(data: NSData)` are better off being failable. There's not much useful detail you can provide for these failures, and it's really nice to be able to use if-let, guard-let, or ?? to handle them instead of having to write an entire do/catch block.

It's helpful to have both a hammer *and* a screwdriver in your toolkit, lest you be forced to treat everything like a nail.

···

--
Brent Royal-Gordon
Architechies

Just to iterate returning an optional as an error I still think is fine for normal functions.
But for the reasons I outlined above I think it's problematic for inits.
Of course two simpler ways towards solving it would to have a guide to explain best practice of when to use fallible init vs a throw.
Also all falliable inits perhaps should have ? In their name (and maybe functions who return one too) Or at least be allowed to give the function a name with ? In it.
In Ruby ? And ! Were nice explicit ways of saying this returns a Bool or this does something dangerous. Having this in swift or something like it would be a great way of making optional functions easier but I'm not sure how desirable this is.
Hence my original proposal is just limited to inits where unexpected errors are far more likely to occur than a function.

···

Sent from Supmenow.com

On Thu, Mar 3, 2016 at 12:07 AM -0800, "Patrick Pijnappel via swift-evolution" <swift-evolution@swift.org> wrote:

The error handdling model as described in swift/ErrorHandlingRationale.rst at main · apple/swift · GitHub is very sensible and consistently applied throughout the language.
Returning an optional is a simplified form of returning an error when there is only one straightforward way of failing. This is a very common case and is simpler than using an error, for which you need to: 1) call w/ try? 2) add 'throws' to the function 3) return some kind of error instance of some type
On Thursday, 3 March 2016, David Hart via swift-evolution <swift-evolution@swift.org> wrote:
The reasoning for me is that they help describe the difference between a function that can return a nil value as part of it's normal operation and a function that can encounter an unexpected error.
On 03 Mar 2016, at 00:44, Ross O'Brien via swift-evolution <swift-evolution@swift.org> wrote:

At the risk of appearing glib or naive - which isn't my intention, I'd like to know the answer - is there not a similar argument to be made for any function which returns an optional instead of throwing a more descriptive error? Asking an array for its first element returns an optional because of the possibility it might have no elements in it; should this throw an error instead of being 'failable'?
On Wed, Mar 2, 2016 at 11:35 PM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

On 2 Mar 2016, at 23:07, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:
On Mar 2, 2016, at 1:11 PM, James Campbell via swift-evolution <swift-evolution@swift.org> wrote:

Given that we now have error handling and availability checks does it make sense to have Failable Initializers which date back to Swift 1.1?

Our error handling schema (swift/ErrorHandlingRationale.rst at main · apple/swift · GitHub) defines how error conditions are handled, and one important class of them (e.g. the "string to int" case) is best modeled as returning an optional. This works really well in practice for functions/methods in general.
Could you give an example of why failable is the better fit here? To me the following two statements are identical:
  let a = FailableType() let b = try? ThrowableType()
Except that in the latter case the try? is more explicit about what is happening (and that it can fail), and I have the option of catching the error to find out more about what went wrong. With some optimisation it should be possible for try? to be just as efficient as a failable initialiser I think.
That said, the failable initialiser could have the same explicit call syntax if it required a trailing question-mark, e.g:
  let a = FailableType()?
As currently the only indicator is on the initialiser declaration itself. Still, when it comes to debugging I’ve found it very useful to force myself to use error handling instead, as it means I have to give reasons for why something failed, which can make it easier to track issues when they do arise.
_______________________________________________

swift-evolution mailing list

swift-evolution@swift.org

https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Returning an optional is a simplified form of returning an error when there is only one straightforward way of failing. This is a very common case and is simpler than using an error, for which you need to: 1) call w/ try? 2) add 'throws' to the function 3) return some kind of error instance of some type

How common is it really though? I hardly ever see it come up, but maybe I’m the one doing something unusual?

For me, checking what the return value of an initialiser is is kind of strange to me, as I just expect it to be an instance of whatever type I asked for. Error handling forces you to do something about the possibility of a failure.

···

On 3 Mar 2016, at 08:07, Patrick Pijnappel via swift-evolution <swift-evolution@swift.org> wrote:

On 2 Mar 2016, at 23:44, Ross O'Brien <narrativium+swift@gmail.com> wrote:

At the risk of appearing glib or naive - which isn't my intention, I'd like to know the answer - is there not a similar argument to be made for any function which returns an optional instead of throwing a more descriptive error? Asking an array for its first element returns an optional because of the possibility it might have no elements in it; should this throw an error instead of being 'failable’?

An optional to me represents something perfectly normal and expected happening that just has no result; i.e- in the case of an array it’s perfectly fine for it to contain no elements, so looking at the first one can’t return a concrete result.

This differs from using a subscript into the array with an invalid index, as with Swift’s index type model you’re not supposed to retain invalid indices into an array that has changed (a lot of the methods of Array specifically state that they disassociate indices with respect to self). So attempting to use a subscript to get an element that doesn’t exist means you’re using an invalid index you shouldn’t have retained, so an error makes sense in that case, vs. returning nil. I admit it’s an easy one to forget since Array indices are just Ints, but they could just as easily be of type ArrayIndex, so you really should limit yourself to index-specific features such as .predecessor(), .successor(), .advancedBy(), .distanceTo() and comparisons with startIndex and endIndex.

I dunno, it’s not a critical thing to change perhaps, but to me a failable/nilable initialiser doesn’t represent a failure as explicitly as error handling does, it also doesn’t force a developer using it to handle that error (even if it’s just to pop a try? in front) or force developer creating it to give a reason why the failure occurred.

True but in my example above for parsing a JSON into a model I can do this:

class Model {

let property: String
let property1: String
let property2: String
let property3: String

init?(json: [String: AnyObject]) {

guard property = json["property"] as? String else {
return nil
}

guard property = json["property1"] as? String else {
return nil
}

guard property = json["property2"] as? String else {
return nil
}

guard property = json["property3"] as? String else {
return nil
}

}

}

There is a lot of boilerplate for very little information and I'm worried
by letting people initialize without returning an error we will get complex
objects like this being constructed and failing for no reason.

Compare this to error handling:

class Model {

let property: String
let property1: String
let property2: String
let property3: String

init?(json: [String: AnyObject]) throws {

property = try json.require("property")
property1 = try json.require("property1")
property2 = try json.require("property2")
property3 = try json.require("property3")

}

}

Require reads the key from the dict and tries to cast it to the same type
as the variable its being assigned to and throws an error if this fails
(like it doesn't exist or it can't be casted). This has much less
boilerplate, its easier to read and also we can throw an error saying ("We
couldn't parse property1").

Some frameworks like Freddy JSON so something similar to this but with a
much more complex model using Enums and it involves setting a bunch of
parameters to tell the library when to throw a runtime error or not if it
can't find something which if not handled correctly can cause a crash.

We could make this even simpler yet if we could somehow treat casting as an
error:

class Model {

let property: String
let property1: String
let property2: String
let property3: String

init?(json: [String: AnyObject]) throws {

property = try json["property"] as String
property1 = try json["property1"] as String
property2 = try json["property2"] as String
property3 = try json["property3"] as String

}

}

If casting fails it throws an error, unfortunately we lose error
information about the key so probably having a casting method like the one
above is probable better. But in someways it explains what is happening.

···

*___________________________________*

*James⎥Head of Trolls*

*james@supmenow.com <james@supmenow.com>⎥supmenow.com <http://supmenow.com>*

*Sup*

*Runway East *

*10 Finsbury Square*

*London*

* EC2A 1AF *

On Thu, Mar 3, 2016 at 8:59 AM, Brent Royal-Gordon via swift-evolution < swift-evolution@swift.org> wrote:

> Error handling forces you to do something about the possibility of a
failure.

So does using a failable initializer: the value is in an Optional, so you
can't access it without either testing and unwrapping or just
force-unwrapping. The type system, rather than the `try` requirement, is
what forces you to handle the error, but it's the same idea.

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

True but in my example above for parsing a JSON into a model I can do this:

class Model {

let property: String
let property1: String
let property2: String
let property3: String

init?(json: [String: AnyObject]) {

guard property = json["property"] as? String else {
return nil
}

guard property = json["property1"] as? String else {
return nil
}

guard property = json["property2"] as? String else {
return nil
}

guard property = json["property3"] as? String else {
return nil
}

Just FYI, but you can of course write this as:

guard let property = json["property"] as? String,
          let property2 = json["property1"] as? String,
          let property3 = json["property2"] as? String,
          let property4 = json["property3"] as? String else {
return nil
}

-Chris

···

On Mar 3, 2016, at 1:09 AM, James Campbell via swift-evolution <swift-evolution@swift.org> wrote:

}

}

There is a lot of boilerplate for very little information and I'm worried by letting people initialize without returning an error we will get complex objects like this being constructed and failing for no reason.

Compare this to error handling:

class Model {

let property: String
let property1: String
let property2: String
let property3: String

init?(json: [String: AnyObject]) throws {

property = try json.require("property")
property1 = try json.require("property1")
property2 = try json.require("property2")
property3 = try json.require("property3")

}

}

Require reads the key from the dict and tries to cast it to the same type as the variable its being assigned to and throws an error if this fails (like it doesn't exist or it can't be casted). This has much less boilerplate, its easier to read and also we can throw an error saying ("We couldn't parse property1").

Some frameworks like Freddy JSON so something similar to this but with a much more complex model using Enums and it involves setting a bunch of parameters to tell the library when to throw a runtime error or not if it can't find something which if not handled correctly can cause a crash.

We could make this even simpler yet if we could somehow treat casting as an error:

class Model {

let property: String
let property1: String
let property2: String
let property3: String

init?(json: [String: AnyObject]) throws {

property = try json["property"] as String
property1 = try json["property1"] as String
property2 = try json["property2"] as String
property3 = try json["property3"] as String

}

}

If casting fails it throws an error, unfortunately we lose error information about the key so probably having a casting method like the one above is probable better. But in someways it explains what is happening.

___________________________________

James⎥Head of Trolls

james@supmenow.com <mailto:james@supmenow.com>⎥supmenow.com <http://supmenow.com/&gt;
Sup

Runway East >

10 Finsbury Square

London

> EC2A 1AF

On Thu, Mar 3, 2016 at 8:59 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> Error handling forces you to do something about the possibility of a failure.

So does using a failable initializer: the value is in an Optional, so you can't access it without either testing and unwrapping or just force-unwrapping. The type system, rather than the `try` requirement, is what forces you to handle the error, but it's the same idea.

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

What’s wrong with:

  guard let myInstance = try? ErrorThrowingType() else { return }

This has the exact same flexibility, and works just as well with the ?? operator as a failable initialiser, in fact that’s one of the main reasons why try? was added I think.

Personally I think what it boils down to for me is that these initialisers are failing, which means that an error has occurred, which means that they should use error handling. On the other side I don’t see optionals as representing errors (and they shouldn’t be used to anymore IMO), but instead the result of something that doesn’t have to return a value (but has been used correctly).

···

On 3 Mar 2016, at 09:20, Brent Royal-Gordon <brent@architechies.com> wrote:
it's really nice to be able to use if-let, guard-let, or ?? to handle them instead of having to write an entire do/catch block.

+1 to everything Brent said.

-Thorsten

···

Am 03.03.2016 um 10:20 schrieb Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org>:

class Model {

let property: String
let property1: String
let property2: String
let property3: String

init?(json: [String: AnyObject]) throws {

property = try json.require("property")
property1 = try json.require("property1")
property2 = try json.require("property2")
property3 = try json.require("property3")

}

}

Require reads the key from the dict and tries to cast it to the same type as the variable its being assigned to and throws an error if this fails (like it doesn't exist or it can't be casted). This has much less boilerplate, its easier to read and also we can throw an error saying ("We couldn't parse property1").

You're right, that's an improvement over the failable initializer. *So make this a throwing init instead.* It's not like the existence of failable initializers keeps you from using `throws`.

Meanwhile, things like `Int.init(_: String)` and `NSImage.init(data: NSData)` are better off being failable. There's not much useful detail you can provide for these failures, and it's really nice to be able to use if-let, guard-let, or ?? to handle them instead of having to write an entire do/catch block.

It's helpful to have both a hammer *and* a screwdriver in your toolkit, lest you be forced to treat everything like a nail.

--
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

let i: Int = Int.init(123)
would not compile if that initializer had a return type of Void rather than Int.

No one can argue the observation that init-methods have return values (although I think it's rather uncommon to invoke them that way) — but that is not my point:
Let's imagine I write a library with a numeric type, and define the "+"-operator to perform a multiplication.
Given this,
let x: StringIntLiteralConvertible = 2 + 5
should assign x a value of 10: That is how the operation is defined (like "init" is defined to return self), and according to your argumentation, everything is fine.
Nonetheless, I'd say this operator is inconsistent, because it contradicts to common behavior, and "+" should be linked to addition.
Initializers behave similar (on another level, though):
They have the signature of a void function, they have the body of a void function — but yet they return something.

You are right that this is actually a topic on its own, as "init?" just emphasizes the "oddity", because suddenly there is a need to manually add a return statement for one case...

Tino