I think the current way to initiate models in a Failable Initializer `init?()` is overly verbose and should be shortened down so less boilerplate should be needed.
The current way:
let someProperty: Any
let anotherProperty: Any
init?(data: [String: Any]) {
guard
let someProperty = data["some_key"],
let anotherProperty = data["another_key"]
else {
return nil
}
self. someProperty = someProperty
self. anotherProperty = anotherProperty
}
As you can see we had to use the properties twice (this would also be the case of `if let`) making the initializer twice as long as necessary and becomes a pain to implement when having more than 1 property.
My idea is extending the power of the `guard` statement
Idea:
init?(data: [String: Any]) {
guard
someProperty = data["some_key"], // Currently fails because `self` us used before all stored properties are initialized
anotherProperty = data["another_key"]
else {
return nil
}
}
}
On Tue, Jul 25, 2017 at 5:44 AM, philohan95 via swift-evolution < swift-evolution@swift.org> wrote:
I think the current way to initiate models in a Failable Initializer
`init?()` is overly verbose and should be shortened down so less
boilerplate should be needed.
The current way:
let someProperty: Any
let anotherProperty: Any
init?(data: [String: Any]) {
guard
let someProperty = data["some_key"],
let anotherProperty = data["another_key"]
else {
return nil
}
self. someProperty = someProperty
self. anotherProperty = anotherProperty
}
As you can see we had to use the properties twice (this would also be the
case of `if let`) making the initializer twice as long as necessary and
becomes a pain to implement when having more than 1 property.
My idea is extending the power of the `guard` statement
Idea:
init?(data: [String: Any]) {
guard
someProperty = data["some_key"], // Currently
fails because `self` us used before all stored properties are initialized
anotherProperty = data["another_key"]
else {
return nil
}
}
}
let bar: String
if someCondition {
do { bar = mightReturnOptional() ?? throwNilError() }
catch { return }
} else {
bar = wontReturnOptional()
}
···
On Tue, Jul 25, 2017 at 4:44 AM, philohan95 via swift-evolution < swift-evolution@swift.org> wrote:
As you can see we had to use the properties twice (this would also be the
case of `if let`) making the initializer twice as long as necessary and
becomes a pain to implement when having more than 1 property.
My idea is extending the power of the `guard` statement
Idea:
init?(data: [String: Any]) {
guard
someProperty = data["some_key"], // Currently
fails because `self` us used before all stored properties are initialized
anotherProperty = data["another_key"]
else {
return nil
}
}
}
This was one of the issues I tried to address in my proposal about factory initializers (based on all previous discussions on that topic).
I’d love to see this happen, but much like the reason why I didn’t push the factory initializers proposal to review, I think now’s not the time for this.
The swift dev team has made it clear that they have very strict priorities and stages regarding the release schedule.
I’m afraid at this time, anything that is not a bug-fix or doesn’t align with the current stage’s priorities will be promptly dismissed.
The sad part is that currently there’s no good way of stashing proposals for future revision, so we just gotta keep these in our heads until the time is right.
···
On Jul 25, 2017, at 12:44 PM, philohan95 via swift-evolution <swift-evolution@swift.org> wrote:
I think the current way to initiate models in a Failable Initializer `init?()` is overly verbose and should be shortened down so less boilerplate should be needed.
The current way:
let someProperty: Any
let anotherProperty: Any
init?(data: [String: Any]) {
guard
let someProperty = data["some_key"],
let anotherProperty = data["another_key"]
else {
return nil
}
self. someProperty = someProperty
self. anotherProperty = anotherProperty
}
As you can see we had to use the properties twice (this would also be the case of `if let`) making the initializer twice as long as necessary and becomes a pain to implement when having more than 1 property.
My idea is extending the power of the `guard` statement
Idea:
init?(data: [String: Any]) {
guard
someProperty = data["some_key"], // Currently fails because `self` us used before all stored properties are initialized
anotherProperty = data["another_key"]
else {
return nil
}
}
}
Guard isn’t really the right answer for this, I’d try something like this (where unwrapOrThrow is the obvious generic function you can define yourself):
On Jul 25, 2017, at 2:44 AM, philohan95 via swift-evolution <swift-evolution@swift.org> wrote:
I think the current way to initiate models in a Failable Initializer `init?()` is overly verbose and should be shortened down so less boilerplate should be needed.
The current way:
let someProperty: Any
let anotherProperty: Any
init?(data: [String: Any]) {
guard
let someProperty = data["some_key"],
let anotherProperty = data["another_key"]
else {
return nil
}
self. someProperty = someProperty
self. anotherProperty = anotherProperty
}
Catching and throwing exceptions is not the same as a controlled guard
fail. It’s also quite verbose and requires extra types to be defined
outside the scope of the initializer.
···
On Tue, Jul 25, 2017 at 5:35 PM, Rob Mayoff via swift-evolution < swift-evolution@swift.org> wrote:
On Tue, Jul 25, 2017 at 4:44 AM, philohan95 via swift-evolution < > swift-evolution@swift.org> wrote:
As you can see we had to use the properties twice (this would also be the
case of `if let`) making the initializer twice as long as necessary and
becomes a pain to implement when having more than 1 property.
My idea is extending the power of the `guard` statement
Idea:
init?(data: [String: Any]) {
guard
someProperty = data["some_key"], // Currently
fails because `self` us used before all stored properties are initialized
anotherProperty = data["another_key"]
else {
return nil
}
}
}
I'm not convinced new syntax is necessary. You can get pretty close to
this today. First, put this in your project somewhere:
On 25. Jul 2017, at 18:30, Taylor Swift via swift-evolution <swift-evolution@swift.org> wrote:
I’d be in favor of this.
On Tue, Jul 25, 2017 at 5:44 AM, philohan95 via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I think the current way to initiate models in a Failable Initializer `init?()` is overly verbose and should be shortened down so less boilerplate should be needed.
The current way:
let someProperty: Any
let anotherProperty: Any
init?(data: [String: Any]) {
guard
let someProperty = data["some_key"],
let anotherProperty = data["another_key"]
else {
return nil
}
self. someProperty = someProperty
self. anotherProperty = anotherProperty
}
As you can see we had to use the properties twice (this would also be the case of `if let`) making the initializer twice as long as necessary and becomes a pain to implement when having more than 1 property.
My idea is extending the power of the `guard` statement
Idea:
init?(data: [String: Any]) {
guard
someProperty = data["some_key"], // Currently fails because `self` us used before all stored properties are initialized
anotherProperty = data["another_key"]
else {
return nil
}
}
}
Although I have come across this problem as well (particularly when
initializing from JSON), I don't think the solution is to fundamentally
change initialization behavior like this, because 1. ) that is probably
going to break a good deal of existing code and 2. ) I think that the
introduction of the Codable protocol in Swift 4 will eliminate most cases
where this is really a problem.
···
On Wed, 26 Jul 2017 at 02:30 Taylor Swift via swift-evolution < swift-evolution@swift.org> wrote:
I’d be in favor of this.
On Tue, Jul 25, 2017 at 5:44 AM, philohan95 via swift-evolution < > swift-evolution@swift.org> wrote:
I think the current way to initiate models in a Failable Initializer
`init?()` is overly verbose and should be shortened down so less
boilerplate should be needed.
The current way:
let someProperty: Any
let anotherProperty: Any
init?(data: [String: Any]) {
guard
let someProperty = data["some_key"],
let anotherProperty = data["another_key"]
else {
return nil
}
self. someProperty = someProperty
self. anotherProperty = anotherProperty
}
As you can see we had to use the properties twice (this would also be the
case of `if let`) making the initializer twice as long as necessary and
becomes a pain to implement when having more than 1 property.
My idea is extending the power of the `guard` statement
Idea:
init?(data: [String: Any]) {
guard
someProperty = data["some_key"], // Currently
fails because `self` us used before all stored properties are initialized
anotherProperty = data["another_key"]
else {
return nil
}
}
}
Is there a reason that a throwing unwrap function/operator isn’t part of the standard library? Seems like it would be handy to be able to have a one-liner for attempting to unwrap and throw if it’s nil. Something like
postfix operator .?!
extension Optional {
static postfix func .?!(optional: Optional<Wrapped>) throws -> Wrapped {
switch optional {
case let .some(wrapped):
return wrapped
case .none:
throw UnwrapError()
}
}
}
On Jul 26, 2017, at 12:13 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:
On Jul 25, 2017, at 2:44 AM, philohan95 via swift-evolution <swift-evolution@swift.org> wrote:
I think the current way to initiate models in a Failable Initializer `init?()` is overly verbose and should be shortened down so less boilerplate should be needed.
The current way:
let someProperty: Any
let anotherProperty: Any
init?(data: [String: Any]) {
guard
let someProperty = data["some_key"],
let anotherProperty = data["another_key"]
else {
return nil
}
self. someProperty = someProperty
self. anotherProperty = anotherProperty
}
Guard isn’t really the right answer for this, I’d try something like this (where unwrapOrThrow is the obvious generic function you can define yourself):
I’ll take the opposite stance. Why limit this to initialization? I’d love to be able to guard assignments to *any* variable, whether it’s a property or not:
func foo() {
let bar: String
if someCondition {
guard bar = mightReturnOptional() else {
return
}
} else {
bar = wontReturnOptional()
}
self.doSomethingWith(bar)
}
As opposed to:
func foo() {
let bar: String
if someCondition {
guard let _bar = mightReturnOptional() else {
return
}
bar = _bar
} else {
bar = wontReturnOptional()
}
self.doSomethingWith(bar)
}
Charles
···
On Jul 25, 2017, at 4:13 PM, Niels Andriesse via swift-evolution <swift-evolution@swift.org> wrote:
Although I have come across this problem as well (particularly when initializing from JSON), I don't think the solution is to fundamentally change initialization behavior like this, because 1. ) that is probably going to break a good deal of existing code and 2. ) I think that the introduction of the Codable protocol in Swift 4 will eliminate most cases where this is really a problem.
On Wed, 26 Jul 2017 at 02:30 Taylor Swift via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I’d be in favor of this.
On Tue, Jul 25, 2017 at 5:44 AM, philohan95 via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I think the current way to initiate models in a Failable Initializer `init?()` is overly verbose and should be shortened down so less boilerplate should be needed.
The current way:
let someProperty: Any
let anotherProperty: Any
init?(data: [String: Any]) {
guard
let someProperty = data["some_key"],
let anotherProperty = data["another_key"]
else {
return nil
}
self. someProperty = someProperty
self. anotherProperty = anotherProperty
}
As you can see we had to use the properties twice (this would also be the case of `if let`) making the initializer twice as long as necessary and becomes a pain to implement when having more than 1 property.
My idea is extending the power of the `guard` statement
Idea:
init?(data: [String: Any]) {
guard
someProperty = data["some_key"], // Currently fails because `self` us used before all stored properties are initialized
anotherProperty = data["another_key"]
else {
return nil
}
}
}
This problem is not limited to JSON. I have scads of underscored variables
and guard bindings in my code because of this limitation, though I rarely
work with JSON.
···
On Tue, Jul 25, 2017 at 5:13 PM, Niels Andriesse <andriesseniels@gmail.com> wrote:
Although I have come across this problem as well (particularly when
initializing from JSON), I don't think the solution is to fundamentally
change initialization behavior like this, because 1. ) that is probably
going to break a good deal of existing code and 2. ) I think that the
introduction of the Codable protocol in Swift 4 will eliminate most cases
where this is really a problem.
On Wed, 26 Jul 2017 at 02:30 Taylor Swift via swift-evolution < > swift-evolution@swift.org> wrote:
I’d be in favor of this.
On Tue, Jul 25, 2017 at 5:44 AM, philohan95 via swift-evolution < >> swift-evolution@swift.org> wrote:
I think the current way to initiate models in a Failable Initializer
`init?()` is overly verbose and should be shortened down so less
boilerplate should be needed.
The current way:
let someProperty: Any
let anotherProperty: Any
init?(data: [String: Any]) {
guard
let someProperty = data["some_key"],
let anotherProperty = data["another_key"]
else {
return nil
}
self. someProperty = someProperty
self. anotherProperty = anotherProperty
}
As you can see we had to use the properties twice (this would also be
the case of `if let`) making the initializer twice as long as necessary and
becomes a pain to implement when having more than 1 property.
My idea is extending the power of the `guard` statement
Idea:
init?(data: [String: Any]) {
guard
someProperty = data["some_key"], // Currently
fails because `self` us used before all stored properties are initialized
anotherProperty = data["another_key"]
else {
return nil
}
}
}
Is there a reason that a throwing unwrap function/operator isn’t part of the standard library? Seems like it would be handy to be able to have a one-liner for attempting to unwrap and throw if it’s nil.
?! would be the wrong name, since ! is generally reserved for potentially-trapping operations that should be avoided in most cases.
If you’re going to explore this branch of the design tree, the sensible thing seems to be to (conceptually) carve off some chunk of the operator space for throwing operators (e.g. ^ which could be rationalized as connoting “raising” an error). This would argue for postfix ^ to unwrap-or-throw (as an analog to postfix ?, enabling chaining etc), and would then provide a schema to define other “or throw” operations.
-Chris
···
On Jul 26, 2017, at 9:55 AM, Robert Bennett <rltbennett@icloud.com> wrote:
Something like
postfix operator .?!
extension Optional {
static postfix func .?!(optional: Optional<Wrapped>) throws -> Wrapped {
switch optional {
case let .some(wrapped):
return wrapped
case .none:
throw UnwrapError()
}
}
}
On Jul 26, 2017, at 12:13 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:
On Jul 25, 2017, at 2:44 AM, philohan95 via swift-evolution <swift-evolution@swift.org> wrote:
I think the current way to initiate models in a Failable Initializer `init?()` is overly verbose and should be shortened down so less boilerplate should be needed.
The current way:
let someProperty: Any
let anotherProperty: Any
init?(data: [String: Any]) {
guard
let someProperty = data["some_key"],
let anotherProperty = data["another_key"]
else {
return nil
}
self. someProperty = someProperty
self. anotherProperty = anotherProperty
}
Guard isn’t really the right answer for this, I’d try something like this (where unwrapOrThrow is the obvious generic function you can define yourself):
Makes sense. Off the top of my head, I can imagine the following two operators:
`optional?^` throws some default error if nil
`optional ??^ error` throws `error` if nil
You could have optional throwing chaining as well — basically everywhere the language currently offers a choice of graceful optional or potentially fatal force unwrap, there could be a third option to propagate an error. Is this worth exploring further in a new thread? I feel like this has been discussed and decided against...
···
On Jul 26, 2017, at 4:01 PM, Chris Lattner <clattner@nondot.org> wrote:
On Jul 26, 2017, at 9:55 AM, Robert Bennett <rltbennett@icloud.com> wrote:
Is there a reason that a throwing unwrap function/operator isn’t part of the standard library? Seems like it would be handy to be able to have a one-liner for attempting to unwrap and throw if it’s nil.
?! would be the wrong name, since ! is generally reserved for potentially-trapping operations that should be avoided in most cases.
If you’re going to explore this branch of the design tree, the sensible thing seems to be to (conceptually) carve off some chunk of the operator space for throwing operators (e.g. ^ which could be rationalized as connoting “raising” an error). This would argue for postfix ^ to unwrap-or-throw (as an analog to postfix ?, enabling chaining etc), and would then provide a schema to define other “or throw” operations.
-Chris
Something like
postfix operator .?!
extension Optional {
static postfix func .?!(optional: Optional<Wrapped>) throws -> Wrapped {
switch optional {
case let .some(wrapped):
return wrapped
case .none:
throw UnwrapError()
}
}
}
On Jul 26, 2017, at 12:13 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:
On Jul 25, 2017, at 2:44 AM, philohan95 via swift-evolution <swift-evolution@swift.org> wrote:
I think the current way to initiate models in a Failable Initializer `init?()` is overly verbose and should be shortened down so less boilerplate should be needed.
The current way:
let someProperty: Any
let anotherProperty: Any
init?(data: [String: Any]) {
guard
let someProperty = data["some_key"],
let anotherProperty = data["another_key"]
else {
return nil
}
self. someProperty = someProperty
self. anotherProperty = anotherProperty
}
Guard isn’t really the right answer for this, I’d try something like this (where unwrapOrThrow is the obvious generic function you can define yourself):