[Proposal] Uniform Initialization Syntax

Cool. I have reservations about idea #3, but we can tackle that another
day. (Real life things beckon.) But suffice it to say that I now really,
really like your idea #2.

···

On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the
signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self`
non-optional.
This would make `return nil` less out-of-place, like you said, while still
leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax, while
adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it
to change the signature as well as remove any compiler assumptions about
the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place
initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

So far, we've discussed two ways of interpreting `self = nil`, both of
which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as
counter-intuitive, but recall that `return nil` is just as much of a
special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax
because the initializer notionally has no return value. Personally, I have
always disliked `return nil` in failable initializers for that reason, but
I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because, in
the case of a failable initializer, `return nil` continues to have the same
meaning if we consider the return value of the initializer to be of type
`Self?`. For that reason, I think your idea #2 is quite clever, and it
would go a long way in making `return nil` a lot less odd. It also
increases the expressivity of initializers because it allows one to set the
value of self and also return in one statement, clearly demonstrating the
intention that no other code in the initializer should be run before
returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with

initialization semantics, it provides more uniform syntax and it's a bit
less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more
cumbersome. Implicitly unwrapped optionals are a bit difficult, but this
"variation" of it is much more restrictive then the normal ones, because
unlike normal implicitly unwrapped optionals, this one cannot be accessed
after being assigned nil (and it also cannot be indirectly assigned `nil`,
because escaping `self` is not allowed before full initialization), so
there is only one possible place it can be set to nil and that's directly
in the initializer. This means that `self` can be safely treated as `inout
Self` before being set to nil (and after being set to nil, it doesn't
matter any more because you aren't allowed to access it, due to not being
fully initialized).

I have to say, I don’t like either of these explanations at all. I think
having a “special” IUO is a difficult sell; it is just conceptually too
complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language
wonkier because it currently has a parallel wonky feature in `return nil`
seems like the wrong way to go. In addition, there’s nothing gained here
that cannot be done with a defer statement; of course, defer statements
might not be very elegant, but it would certainly be less wonky than
inventing a new variation on an IUO to allow assignment of nil to self...
For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic and

the restrictions of `self as inout Self!` are imposed by already existing
and well-understood initialization logic, so the provided guarantees don't
really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

I think a good approach would be to have `self = nil` only mean `the
initializer is going to fail` because if your type is
ExpressibleByNilLiteral, it means that the `nil` of your type already
carries the same meaning as if your type was not ExpressibleByNilLiteral
and was an optional instead, so having a failable initializer doesn't
really make sense in that case (since you could've initialized `self` to
its own `nil` in case of failure). Still, some valid use cases may exist,
so the natural (and quite intuitive) way to circumvent this would be to
call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different
thing in an initializer than it does in a function? Essentially, then,
you’re creating your own variation on an implicitly unwrapped optional,
where `self` is of type `inout Self?` for assignment in initializers only
but not for any other purpose. Implicitly unwrapped optionals are hard to
reason about, and having a variation on it would be even harder to
understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however, I
do think Greg is right that it would create more boilerplate than the
current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com> >>> wrote:

The type of `self` could remain `inout Self` inside the failable
initializer. The ability to assign nil would be a compiler magic (much like
`return nil` is compiler magic) that is meant to introduce uniformity to
the initialization logic.

The idea is to define all different ways initialization can take place
and expand them to be used uniformly on both `self` and all its members, as
well as remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
1. delegating initializer
2. assigning to self
3. returning nil

#1: The delegating initializer is pretty much perfect at this point, in
my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside
failable initializers.

#3: The only thing that can be returned from an initializer is `nil`,
which is compiler magic, so we can thing of it as a misnomer (because we
aren't really **returning** anything).

If, for a second, we forget about potential factory initializers,
returning anything from an initializer doesn't make much sense, because an
initializer is conceptually meant to bring an existing object in memory to
a type-specific valid state. This semantic was very explicitly in
Objective-C with `[[MyType alloc] init]`. Especially since even
syntactically, the initializer does not specify any return type, the idea
of returning from an initializer is counter-intuitive both syntactically
and semantically.

The actual *behavior* of `return nil` is very sensible, so the
behavior, I imagine `self = nil`, would largely mean the same (except not
needed to return immediately and allowing non-self-accessing code to be
executed before return). Being able to assign `nil` to a non-optional
(ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to
initialize self to nil? That is what `self = nil` means if `self` is of
type `inout Self`. If `self` is of type `inout Self` and Self is not
ExpressibleByNilLiteral, then it must be an error to assign nil to self.
Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to

initialize an object in-place and doesn't look like it should return
anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init`
syntax could completely flip this logic, but making the initializer
essentially a static function that returns an object. In this case the
initializer could be made to specify the return type (that is the supertype
of all possible factory-created objects) and assigning to self would be
forbidden because there is not self yet:

extension MyProtocol {

public factory init(weCool: Bool) -> MyProtocol {
self = MyImpl() // error: cannot assign to `self` in a factory
initializer
self.init(...) // error: cannot make a delegating initializer call in a
factory initializer
if weCool {
return MyCoolImpl()
} else {
return MyUncoolImpl()
}
}

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2
(as in `self.member = value`), which could be extended in a non-factory
initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while
giving a more reliable performance guarantee that this member will not be
copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

If `self` is not of type `inout Self?`, then what is the type of `self`
such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms to
`ExpressibleByNilLiteral`, in which case you are able to assign `self =
nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped
optionals are no longer their own type, I’m not sure that’s possible. But
even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self`
would have to be of type `inout Self?`–which is intriguing but potentially
more boilerplatey than the status quo.
On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution < >>>> swift-evolution@swift.org> wrote:

Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and
since `self` can only be initialized once, this would mean that after `self
= nil`, you won't be allowed to access `self` in your initializer at
all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to
treat `self` as `inout Self?`, because the only place it can be `nil` is
the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution < >>>>> swift-evolution@swift.org> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable initializers
(essentially making `self` look like `inout Self?` instead of `inout Self`
with magical `return nil`), so that all initializers uniformly can be
written in `self = ...` form for clarity and convenience purposes. This
should, theoretically, be nothing but a `defer { return nil }` type of
rewrite, so I don't see any major difficulties implementing this. This is
especially useful for failable-initializing enums where the main switch
simply assigns to self in all cases and the rest of the initializer does
some post-processing.

I don't see how to avoid source incompatibility and uglification of
failable initializer implementations here. Allowing `self = nil` inside a
failable initializer would require `self` to be an optional. That in turn
would require every use of `self` in the initializer to be nil-checked or
forced. I don't think that loss everywhere outweighs the gain of `self =
nil` in some places.

--
Greg Parker gparker@apple.com Runtime Wrangler

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

Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/master/proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed it wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

···

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Cool. I have reservations about idea #3, but we can tackle that another day. (Real life things beckon.) But suffice it to say that I now really, really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self` non-optional.
This would make `return nil` less out-of-place, like you said, while still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax, while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it to change the signature as well as remove any compiler assumptions about the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
So far, we've discussed two ways of interpreting `self = nil`, both of which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as counter-intuitive, but recall that `return nil` is just as much of a special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax because the initializer notionally has no return value. Personally, I have always disliked `return nil` in failable initializers for that reason, but I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because, in the case of a failable initializer, `return nil` continues to have the same meaning if we consider the return value of the initializer to be of type `Self?`. For that reason, I think your idea #2 is quite clever, and it would go a long way in making `return nil` a lot less odd. It also increases the expressivity of initializers because it allows one to set the value of self and also return in one statement, clearly demonstrating the intention that no other code in the initializer should be run before returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with initialization semantics, it provides more uniform syntax and it's a bit less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more cumbersome. Implicitly unwrapped optionals are a bit difficult, but this "variation" of it is much more restrictive then the normal ones, because unlike normal implicitly unwrapped optionals, this one cannot be accessed after being assigned nil (and it also cannot be indirectly assigned `nil`, because escaping `self` is not allowed before full initialization), so there is only one possible place it can be set to nil and that's directly in the initializer. This means that `self` can be safely treated as `inout Self` before being set to nil (and after being set to nil, it doesn't matter any more because you aren't allowed to access it, due to not being fully initialized).

I have to say, I don’t like either of these explanations at all. I think having a “special” IUO is a difficult sell; it is just conceptually too complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language wonkier because it currently has a parallel wonky feature in `return nil` seems like the wrong way to go. In addition, there’s nothing gained here that cannot be done with a defer statement; of course, defer statements might not be very elegant, but it would certainly be less wonky than inventing a new variation on an IUO to allow assignment of nil to self... For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic and the restrictions of `self as inout Self!` are imposed by already existing and well-understood initialization logic, so the provided guarantees don't really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
I think a good approach would be to have `self = nil` only mean `the initializer is going to fail` because if your type is ExpressibleByNilLiteral, it means that the `nil` of your type already carries the same meaning as if your type was not ExpressibleByNilLiteral and was an optional instead, so having a failable initializer doesn't really make sense in that case (since you could've initialized `self` to its own `nil` in case of failure). Still, some valid use cases may exist, so the natural (and quite intuitive) way to circumvent this would be to call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different thing in an initializer than it does in a function? Essentially, then, you’re creating your own variation on an implicitly unwrapped optional, where `self` is of type `inout Self?` for assignment in initializers only but not for any other purpose. Implicitly unwrapped optionals are hard to reason about, and having a variation on it would be even harder to understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however, I do think Greg is right that it would create more boilerplate than the current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
The type of `self` could remain `inout Self` inside the failable initializer. The ability to assign nil would be a compiler magic (much like `return nil` is compiler magic) that is meant to introduce uniformity to the initialization logic.

The idea is to define all different ways initialization can take place and expand them to be used uniformly on both `self` and all its members, as well as remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
  1. delegating initializer
  2. assigning to self
  3. returning nil

#1: The delegating initializer is pretty much perfect at this point, in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside failable initializers.

#3: The only thing that can be returned from an initializer is `nil`, which is compiler magic, so we can thing of it as a misnomer (because we aren't really **returning** anything).

If, for a second, we forget about potential factory initializers, returning anything from an initializer doesn't make much sense, because an initializer is conceptually meant to bring an existing object in memory to a type-specific valid state. This semantic was very explicitly in Objective-C with `[[MyType alloc] init]`. Especially since even syntactically, the initializer does not specify any return type, the idea of returning from an initializer is counter-intuitive both syntactically and semantically.

The actual *behavior* of `return nil` is very sensible, so the behavior, I imagine `self = nil`, would largely mean the same (except not needed to return immediately and allowing non-self-accessing code to be executed before return). Being able to assign `nil` to a non-optional (ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to initialize self to nil? That is what `self = nil` means if `self` is of type `inout Self`. If `self` is of type `inout Self` and Self is not ExpressibleByNilLiteral, then it must be an error to assign nil to self. Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to initialize an object in-place and doesn't look like it should return anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init` syntax could completely flip this logic, but making the initializer essentially a static function that returns an object. In this case the initializer could be made to specify the return type (that is the supertype of all possible factory-created objects) and assigning to self would be forbidden because there is not self yet:

extension MyProtocol {

  public factory init(weCool: Bool) -> MyProtocol {
    self = MyImpl() // error: cannot assign to `self` in a factory initializer
    self.init(...) // error: cannot make a delegating initializer call in a factory initializer
    if weCool {
      return MyCoolImpl()
    } else {
      return MyUncoolImpl()
    }
  }

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2 (as in `self.member = value`), which could be extended in a non-factory initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while giving a more reliable performance guarantee that this member will not be copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

If `self` is not of type `inout Self?`, then what is the type of `self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms to `ExpressibleByNilLiteral`, in which case you are able to assign `self = nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped optionals are no longer their own type, I’m not sure that’s possible. But even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self` would have to be of type `inout Self?`–which is intriguing but potentially more boilerplatey than the status quo.
On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and since `self` can only be initialized once, this would mean that after `self = nil`, you won't be allowed to access `self` in your initializer at all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to treat `self` as `inout Self?`, because the only place it can be `nil` is the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com <mailto:gparker@apple.com>> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable initializers (essentially making `self` look like `inout Self?` instead of `inout Self` with magical `return nil`), so that all initializers uniformly can be written in `self = ...` form for clarity and convenience purposes. This should, theoretically, be nothing but a `defer { return nil }` type of rewrite, so I don't see any major difficulties implementing this. This is especially useful for failable-initializing enums where the main switch simply assigns to self in all cases and the rest of the initializer does some post-processing.

I don't see how to avoid source incompatibility and uglification of failable initializer implementations here. Allowing `self = nil` inside a failable initializer would require `self` to be an optional. That in turn would require every use of `self` in the initializer to be nil-checked or forced. I don't think that loss everywhere outweighs the gain of `self = nil` in some places.

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler

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

Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/
master/proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed it
wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

This is a very interesting read. We did not discuss the 'indirect' idea at
all on this list. Did you come up with it just now? In any case, my
suggestion as to moving forward would be this:

- Do you feel that both halves of your draft (expanding `return` in
initializers, and `indirect` initializers) should absolutely be one
proposal, or can they be separated?

a) If they can be separated because each half has individual merit, then
these ideas may be more likely to succeed as separate proposals, as each
can be critiqued fully and judged independently as digestible units.

b) If you intend to tackle all your ideas all at once, that's going to be a
much bigger change--in terms of review effort, likely bikeshedding, and
implementation effort. It'll probably be best to solicit initial feedback
on this list first about `indirect` initializers, even if just to
familiarize the community with the idea, before launching into a pitch of
the whole proposal.

···

On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Cool. I have reservations about idea #3, but we can tackle that another
day. (Real life things beckon.) But suffice it to say that I now really,
really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the
signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are
non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self`
non-optional.
This would make `return nil` less out-of-place, like you said, while
still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax,
while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it
to change the signature as well as remove any compiler assumptions about
the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place
initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

So far, we've discussed two ways of interpreting `self = nil`, both of
which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as
counter-intuitive, but recall that `return nil` is just as much of a
special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax
because the initializer notionally has no return value. Personally, I have
always disliked `return nil` in failable initializers for that reason, but
I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because,
in the case of a failable initializer, `return nil` continues to have the
same meaning if we consider the return value of the initializer to be of
type `Self?`. For that reason, I think your idea #2 is quite clever, and it
would go a long way in making `return nil` a lot less odd. It also
increases the expressivity of initializers because it allows one to set the
value of self and also return in one statement, clearly demonstrating the
intention that no other code in the initializer should be run before
returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with

initialization semantics, it provides more uniform syntax and it's a bit
less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more
cumbersome. Implicitly unwrapped optionals are a bit difficult, but this
"variation" of it is much more restrictive then the normal ones, because
unlike normal implicitly unwrapped optionals, this one cannot be accessed
after being assigned nil (and it also cannot be indirectly assigned `nil`,
because escaping `self` is not allowed before full initialization), so
there is only one possible place it can be set to nil and that's directly
in the initializer. This means that `self` can be safely treated as `inout
Self` before being set to nil (and after being set to nil, it doesn't
matter any more because you aren't allowed to access it, due to not being
fully initialized).

I have to say, I don’t like either of these explanations at all. I think
having a “special” IUO is a difficult sell; it is just conceptually too
complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language
wonkier because it currently has a parallel wonky feature in `return nil`
seems like the wrong way to go. In addition, there’s nothing gained here
that cannot be done with a defer statement; of course, defer statements
might not be very elegant, but it would certainly be less wonky than
inventing a new variation on an IUO to allow assignment of nil to self...
For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic and

the restrictions of `self as inout Self!` are imposed by already existing
and well-understood initialization logic, so the provided guarantees don't
really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com> >>> wrote:

I think a good approach would be to have `self = nil` only mean `the
initializer is going to fail` because if your type is
ExpressibleByNilLiteral, it means that the `nil` of your type already
carries the same meaning as if your type was not ExpressibleByNilLiteral
and was an optional instead, so having a failable initializer doesn't
really make sense in that case (since you could've initialized `self` to
its own `nil` in case of failure). Still, some valid use cases may exist,
so the natural (and quite intuitive) way to circumvent this would be to
call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different
thing in an initializer than it does in a function? Essentially, then,
you’re creating your own variation on an implicitly unwrapped optional,
where `self` is of type `inout Self?` for assignment in initializers only
but not for any other purpose. Implicitly unwrapped optionals are hard to
reason about, and having a variation on it would be even harder to
understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however, I
do think Greg is right that it would create more boilerplate than the
current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com> >>>> wrote:

The type of `self` could remain `inout Self` inside the failable
initializer. The ability to assign nil would be a compiler magic (much like
`return nil` is compiler magic) that is meant to introduce uniformity to
the initialization logic.

The idea is to define all different ways initialization can take place
and expand them to be used uniformly on both `self` and all its members, as
well as remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
1. delegating initializer
2. assigning to self
3. returning nil

#1: The delegating initializer is pretty much perfect at this point,
in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside
failable initializers.

#3: The only thing that can be returned from an initializer is `nil`,
which is compiler magic, so we can thing of it as a misnomer (because we
aren't really **returning** anything).

If, for a second, we forget about potential factory initializers,
returning anything from an initializer doesn't make much sense, because an
initializer is conceptually meant to bring an existing object in memory to
a type-specific valid state. This semantic was very explicitly in
Objective-C with `[[MyType alloc] init]`. Especially since even
syntactically, the initializer does not specify any return type, the idea
of returning from an initializer is counter-intuitive both syntactically
and semantically.

The actual *behavior* of `return nil` is very sensible, so the
behavior, I imagine `self = nil`, would largely mean the same (except not
needed to return immediately and allowing non-self-accessing code to be
executed before return). Being able to assign `nil` to a non-optional
(ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to
initialize self to nil? That is what `self = nil` means if `self` is of
type `inout Self`. If `self` is of type `inout Self` and Self is not
ExpressibleByNilLiteral, then it must be an error to assign nil to self.
Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to

initialize an object in-place and doesn't look like it should return
anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init`
syntax could completely flip this logic, but making the initializer
essentially a static function that returns an object. In this case the
initializer could be made to specify the return type (that is the supertype
of all possible factory-created objects) and assigning to self would be
forbidden because there is not self yet:

extension MyProtocol {

public factory init(weCool: Bool) -> MyProtocol {
self = MyImpl() // error: cannot assign to `self` in a factory
initializer
self.init(...) // error: cannot make a delegating initializer call in
a factory initializer
if weCool {
return MyCoolImpl()
} else {
return MyUncoolImpl()
}
}

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2
(as in `self.member = value`), which could be extended in a non-factory
initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while
giving a more reliable performance guarantee that this member will not be
copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

If `self` is not of type `inout Self?`, then what is the type of
`self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms to
`ExpressibleByNilLiteral`, in which case you are able to assign `self =
nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped
optionals are no longer their own type, I’m not sure that’s possible. But
even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self`
would have to be of type `inout Self?`–which is intriguing but potentially
more boilerplatey than the status quo.
On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution < >>>>> swift-evolution@swift.org> wrote:

Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and
since `self` can only be initialized once, this would mean that after `self
= nil`, you won't be allowed to access `self` in your initializer at
all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to
treat `self` as `inout Self?`, because the only place it can be `nil` is
the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution < >>>>>> swift-evolution@swift.org> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable initializers
(essentially making `self` look like `inout Self?` instead of `inout Self`
with magical `return nil`), so that all initializers uniformly can be
written in `self = ...` form for clarity and convenience purposes. This
should, theoretically, be nothing but a `defer { return nil }` type of
rewrite, so I don't see any major difficulties implementing this. This is
especially useful for failable-initializing enums where the main switch
simply assigns to self in all cases and the rest of the initializer does
some post-processing.

I don't see how to avoid source incompatibility and uglification of
failable initializer implementations here. Allowing `self = nil` inside a
failable initializer would require `self` to be an optional. That in turn
would require every use of `self` in the initializer to be nil-checked or
forced. I don't think that loss everywhere outweighs the gain of `self =
nil` in some places.

--
Greg Parker gparker@apple.com Runtime Wrangler

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

This is a very interesting read.

Thanks you! I tried to make it as clear and detailed as possible. :slightly_smiling_face:

We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

I was writing the proposal and was just about to write `factory init`, when it occurred to me: enums already have a keyword that does something very similar. It seemed to me that an initializer that doesn't initialize the instance in-place, but returns a completely separate instance from somewhere else, is kinda "indirectly" initializing the instance. Plus, the already established keyword and its semantic would reduce the learning curve for this new feature and separate it from a single specific use case (the "factory method" pattern).

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

I think the `return` can be easily implemented first, while opening up an opportunity to later implement `indirect init`. The reason why I unified them was that the `return` idea on its own has very limited merit and could the thought of as a low-priority cosmetic enhancement. I wouldn't want it to be viewed that way because the primary purpose of that idea is to enable `indirect init` (which Cocoa and Cocoa Touch developers would be very happy about).

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

Very good point. The challenge is to correctly separate them, without losing context in their respective proposals and without bleeding the proposals into each other.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

I'd never send a pull request to swift-evolution without thoroughly discussing it here. I just though, if I'm going to write a whole proposal with examples and motivation, it would be easier to demonstrate it and discuss in with the community If I just went ahead and wrote the whole thing and sent the link. This way it would be clearer to the reader and the discussed changes would be accurately reflected by the commits I'd make to my proposal.

Original Message

···

On Jun 10, 2017, at 2:38 AM, Daryle Walker via swift-evolution <swift-evolution@swift.org> wrote:

On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/master/proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed it wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

This is a very interesting read. We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Cool. I have reservations about idea #3, but we can tackle that another day. (Real life things beckon.) But suffice it to say that I now really, really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self` non-optional.
This would make `return nil` less out-of-place, like you said, while still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax, while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it to change the signature as well as remove any compiler assumptions about the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
So far, we've discussed two ways of interpreting `self = nil`, both of which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as counter-intuitive, but recall that `return nil` is just as much of a special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax because the initializer notionally has no return value. Personally, I have always disliked `return nil` in failable initializers for that reason, but I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because, in the case of a failable initializer, `return nil` continues to have the same meaning if we consider the return value of the initializer to be of type `Self?`. For that reason, I think your idea #2 is quite clever, and it would go a long way in making `return nil` a lot less odd. It also increases the expressivity of initializers because it allows one to set the value of self and also return in one statement, clearly demonstrating the intention that no other code in the initializer should be run before returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with initialization semantics, it provides more uniform syntax and it's a bit less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more cumbersome. Implicitly unwrapped optionals are a bit difficult, but this "variation" of it is much more restrictive then the normal ones, because unlike normal implicitly unwrapped optionals, this one cannot be accessed after being assigned nil (and it also cannot be indirectly assigned `nil`, because escaping `self` is not allowed before full initialization), so there is only one possible place it can be set to nil and that's directly in the initializer. This means that `self` can be safely treated as `inout Self` before being set to nil (and after being set to nil, it doesn't matter any more because you aren't allowed to access it, due to not being fully initialized).

I have to say, I don’t like either of these explanations at all. I think having a “special” IUO is a difficult sell; it is just conceptually too complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language wonkier because it currently has a parallel wonky feature in `return nil` seems like the wrong way to go. In addition, there’s nothing gained here that cannot be done with a defer statement; of course, defer statements might not be very elegant, but it would certainly be less wonky than inventing a new variation on an IUO to allow assignment of nil to self... For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic and the restrictions of `self as inout Self!` are imposed by already existing and well-understood initialization logic, so the provided guarantees don't really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
I think a good approach would be to have `self = nil` only mean `the initializer is going to fail` because if your type is ExpressibleByNilLiteral, it means that the `nil` of your type already carries the same meaning as if your type was not ExpressibleByNilLiteral and was an optional instead, so having a failable initializer doesn't really make sense in that case (since you could've initialized `self` to its own `nil` in case of failure). Still, some valid use cases may exist, so the natural (and quite intuitive) way to circumvent this would be to call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different thing in an initializer than it does in a function? Essentially, then, you’re creating your own variation on an implicitly unwrapped optional, where `self` is of type `inout Self?` for assignment in initializers only but not for any other purpose. Implicitly unwrapped optionals are hard to reason about, and having a variation on it would be even harder to understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however, I do think Greg is right that it would create more boilerplate than the current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
The type of `self` could remain `inout Self` inside the failable initializer. The ability to assign nil would be a compiler magic (much like `return nil` is compiler magic) that is meant to introduce uniformity to the initialization logic.

The idea is to define all different ways initialization can take place and expand them to be used uniformly on both `self` and all its members, as well as remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
  1. delegating initializer
  2. assigning to self
  3. returning nil

#1: The delegating initializer is pretty much perfect at this point, in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside failable initializers.

#3: The only thing that can be returned from an initializer is `nil`, which is compiler magic, so we can thing of it as a misnomer (because we aren't really **returning** anything).

If, for a second, we forget about potential factory initializers, returning anything from an initializer doesn't make much sense, because an initializer is conceptually meant to bring an existing object in memory to a type-specific valid state. This semantic was very explicitly in Objective-C with `[[MyType alloc] init]`. Especially since even syntactically, the initializer does not specify any return type, the idea of returning from an initializer is counter-intuitive both syntactically and semantically.

The actual *behavior* of `return nil` is very sensible, so the behavior, I imagine `self = nil`, would largely mean the same (except not needed to return immediately and allowing non-self-accessing code to be executed before return). Being able to assign `nil` to a non-optional (ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to initialize self to nil? That is what `self = nil` means if `self` is of type `inout Self`. If `self` is of type `inout Self` and Self is not ExpressibleByNilLiteral, then it must be an error to assign nil to self. Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to initialize an object in-place and doesn't look like it should return anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init` syntax could completely flip this logic, but making the initializer essentially a static function that returns an object. In this case the initializer could be made to specify the return type (that is the supertype of all possible factory-created objects) and assigning to self would be forbidden because there is not self yet:

extension MyProtocol {

  public factory init(weCool: Bool) -> MyProtocol {
    self = MyImpl() // error: cannot assign to `self` in a factory initializer
    self.init(...) // error: cannot make a delegating initializer call in a factory initializer
    if weCool {
      return MyCoolImpl()
    } else {
      return MyUncoolImpl()
    }
  }

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2 (as in `self.member = value`), which could be extended in a non-factory initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while giving a more reliable performance guarantee that this member will not be copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

If `self` is not of type `inout Self?`, then what is the type of `self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms to `ExpressibleByNilLiteral`, in which case you are able to assign `self = nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped optionals are no longer their own type, I’m not sure that’s possible. But even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self` would have to be of type `inout Self?`–which is intriguing but potentially more boilerplatey than the status quo.
On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and since `self` can only be initialized once, this would mean that after `self = nil`, you won't be allowed to access `self` in your initializer at all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to treat `self` as `inout Self?`, because the only place it can be `nil` is the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com <mailto:gparker@apple.com>> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable initializers (essentially making `self` look like `inout Self?` instead of `inout Self` with magical `return nil`), so that all initializers uniformly can be written in `self = ...` form for clarity and convenience purposes. This should, theoretically, be nothing but a `defer { return nil }` type of rewrite, so I don't see any major difficulties implementing this. This is especially useful for failable-initializing enums where the main switch simply assigns to self in all cases and the rest of the initializer does some post-processing.

I don't see how to avoid source incompatibility and uglification of failable initializer implementations here. Allowing `self = nil` inside a failable initializer would require `self` to be an optional. That in turn would require every use of `self` in the initializer to be nil-checked or forced. I don't think that loss everywhere outweighs the gain of `self = nil` in some places.

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler

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

Hi Gor :wave:

I’m very much in fan of a unified initialization syntax. I submitted my own proposal for factory initializers a while back, but since it wasn’t a focus of Swift 3 or 4 I haven’t followed up on it recently. In the time since last working on it, I came to my own conclusion that rather than focusing on factory initialization, the overall initialization process should be simplified, which I’m glad to see someone else has realized as well :-)

Here’s my proposal for reference: Proposal: Factory Initializers by rileytestut · Pull Request #247 · apple/swift-evolution · GitHub Originally I used the “factory” keyword, but I think your “indirect” keyword may be a better fit (since it has precedent in the language and is not limited to “just” being about factory initialization). To divide your proposal up into smaller pieces for review, maybe we could update my proposal to use your indirect keyword, and then start a separate topic/proposal for the remaining aspects of your proposal? I agree that splitting it into smaller chunks may be better for the process.

Let me know what you think!

Riley

···

On Jun 10, 2017, at 3:33 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org> wrote:

This is a very interesting read.

Thanks you! I tried to make it as clear and detailed as possible. :slightly_smiling_face:

We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

I was writing the proposal and was just about to write `factory init`, when it occurred to me: enums already have a keyword that does something very similar. It seemed to me that an initializer that doesn't initialize the instance in-place, but returns a completely separate instance from somewhere else, is kinda "indirectly" initializing the instance. Plus, the already established keyword and its semantic would reduce the learning curve for this new feature and separate it from a single specific use case (the "factory method" pattern).

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

I think the `return` can be easily implemented first, while opening up an opportunity to later implement `indirect init`. The reason why I unified them was that the `return` idea on its own has very limited merit and could the thought of as a low-priority cosmetic enhancement. I wouldn't want it to be viewed that way because the primary purpose of that idea is to enable `indirect init` (which Cocoa and Cocoa Touch developers would be very happy about).

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

Very good point. The challenge is to correctly separate them, without losing context in their respective proposals and without bleeding the proposals into each other.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

I'd never send a pull request to swift-evolution without thoroughly discussing it here. I just though, if I'm going to write a whole proposal with examples and motivation, it would be easier to demonstrate it and discuss in with the community If I just went ahead and wrote the whole thing and sent the link. This way it would be clearer to the reader and the discussed changes would be accurately reflected by the commits I'd make to my proposal.

Original Message

On Jun 10, 2017, at 2:38 AM, Daryle Walker via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/master/proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed it wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

This is a very interesting read. We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Cool. I have reservations about idea #3, but we can tackle that another day. (Real life things beckon.) But suffice it to say that I now really, really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self` non-optional.
This would make `return nil` less out-of-place, like you said, while still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax, while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it to change the signature as well as remove any compiler assumptions about the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
So far, we've discussed two ways of interpreting `self = nil`, both of which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as counter-intuitive, but recall that `return nil` is just as much of a special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax because the initializer notionally has no return value. Personally, I have always disliked `return nil` in failable initializers for that reason, but I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because, in the case of a failable initializer, `return nil` continues to have the same meaning if we consider the return value of the initializer to be of type `Self?`. For that reason, I think your idea #2 is quite clever, and it would go a long way in making `return nil` a lot less odd. It also increases the expressivity of initializers because it allows one to set the value of self and also return in one statement, clearly demonstrating the intention that no other code in the initializer should be run before returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with initialization semantics, it provides more uniform syntax and it's a bit less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more cumbersome. Implicitly unwrapped optionals are a bit difficult, but this "variation" of it is much more restrictive then the normal ones, because unlike normal implicitly unwrapped optionals, this one cannot be accessed after being assigned nil (and it also cannot be indirectly assigned `nil`, because escaping `self` is not allowed before full initialization), so there is only one possible place it can be set to nil and that's directly in the initializer. This means that `self` can be safely treated as `inout Self` before being set to nil (and after being set to nil, it doesn't matter any more because you aren't allowed to access it, due to not being fully initialized).

I have to say, I don’t like either of these explanations at all. I think having a “special” IUO is a difficult sell; it is just conceptually too complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language wonkier because it currently has a parallel wonky feature in `return nil` seems like the wrong way to go. In addition, there’s nothing gained here that cannot be done with a defer statement; of course, defer statements might not be very elegant, but it would certainly be less wonky than inventing a new variation on an IUO to allow assignment of nil to self... For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic and the restrictions of `self as inout Self!` are imposed by already existing and well-understood initialization logic, so the provided guarantees don't really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
I think a good approach would be to have `self = nil` only mean `the initializer is going to fail` because if your type is ExpressibleByNilLiteral, it means that the `nil` of your type already carries the same meaning as if your type was not ExpressibleByNilLiteral and was an optional instead, so having a failable initializer doesn't really make sense in that case (since you could've initialized `self` to its own `nil` in case of failure). Still, some valid use cases may exist, so the natural (and quite intuitive) way to circumvent this would be to call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different thing in an initializer than it does in a function? Essentially, then, you’re creating your own variation on an implicitly unwrapped optional, where `self` is of type `inout Self?` for assignment in initializers only but not for any other purpose. Implicitly unwrapped optionals are hard to reason about, and having a variation on it would be even harder to understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however, I do think Greg is right that it would create more boilerplate than the current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
The type of `self` could remain `inout Self` inside the failable initializer. The ability to assign nil would be a compiler magic (much like `return nil` is compiler magic) that is meant to introduce uniformity to the initialization logic.

The idea is to define all different ways initialization can take place and expand them to be used uniformly on both `self` and all its members, as well as remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
  1. delegating initializer
  2. assigning to self
  3. returning nil

#1: The delegating initializer is pretty much perfect at this point, in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside failable initializers.

#3: The only thing that can be returned from an initializer is `nil`, which is compiler magic, so we can thing of it as a misnomer (because we aren't really **returning** anything).

If, for a second, we forget about potential factory initializers, returning anything from an initializer doesn't make much sense, because an initializer is conceptually meant to bring an existing object in memory to a type-specific valid state. This semantic was very explicitly in Objective-C with `[[MyType alloc] init]`. Especially since even syntactically, the initializer does not specify any return type, the idea of returning from an initializer is counter-intuitive both syntactically and semantically.

The actual *behavior* of `return nil` is very sensible, so the behavior, I imagine `self = nil`, would largely mean the same (except not needed to return immediately and allowing non-self-accessing code to be executed before return). Being able to assign `nil` to a non-optional (ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to initialize self to nil? That is what `self = nil` means if `self` is of type `inout Self`. If `self` is of type `inout Self` and Self is not ExpressibleByNilLiteral, then it must be an error to assign nil to self. Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to initialize an object in-place and doesn't look like it should return anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init` syntax could completely flip this logic, but making the initializer essentially a static function that returns an object. In this case the initializer could be made to specify the return type (that is the supertype of all possible factory-created objects) and assigning to self would be forbidden because there is not self yet:

extension MyProtocol {

  public factory init(weCool: Bool) -> MyProtocol {
    self = MyImpl() // error: cannot assign to `self` in a factory initializer
    self.init(...) // error: cannot make a delegating initializer call in a factory initializer
    if weCool {
      return MyCoolImpl()
    } else {
      return MyUncoolImpl()
    }
  }

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2 (as in `self.member = value`), which could be extended in a non-factory initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while giving a more reliable performance guarantee that this member will not be copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

If `self` is not of type `inout Self?`, then what is the type of `self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms to `ExpressibleByNilLiteral`, in which case you are able to assign `self = nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped optionals are no longer their own type, I’m not sure that’s possible. But even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self` would have to be of type `inout Self?`–which is intriguing but potentially more boilerplatey than the status quo.
On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and since `self` can only be initialized once, this would mean that after `self = nil`, you won't be allowed to access `self` in your initializer at all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to treat `self` as `inout Self?`, because the only place it can be `nil` is the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com <mailto:gparker@apple.com>> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable initializers (essentially making `self` look like `inout Self?` instead of `inout Self` with magical `return nil`), so that all initializers uniformly can be written in `self = ...` form for clarity and convenience purposes. This should, theoretically, be nothing but a `defer { return nil }` type of rewrite, so I don't see any major difficulties implementing this. This is especially useful for failable-initializing enums where the main switch simply assigns to self in all cases and the rest of the initializer does some post-processing.

I don't see how to avoid source incompatibility and uglification of failable initializer implementations here. Allowing `self = nil` inside a failable initializer would require `self` to be an optional. That in turn would require every use of `self` in the initializer to be nil-checked or forced. I don't think that loss everywhere outweighs the gain of `self = nil` in some places.

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler

_______________________________________________
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

Hi, Riley!

I think that's a great idea! We can merge the second part of my proposal (the `indirect init`) into your one and refine and consolidate the prerequisite proposal (about returning from `init` and possibly in-place member initializers) and bunch them up into a proposal cluster (the way swift coders did).
Feel free to tear out any chunks from my proposal, while I think about a more in-depth rationale about revamping initialization syntax. :slightly_smiling_face:

···

On Jun 10, 2017, at 8:36 PM, Riley Testut <rileytestut@gmail.com> wrote:

Hi Gor :wave:

I’m very much in fan of a unified initialization syntax. I submitted my own proposal for factory initializers a while back, but since it wasn’t a focus of Swift 3 or 4 I haven’t followed up on it recently. In the time since last working on it, I came to my own conclusion that rather than focusing on factory initialization, the overall initialization process should be simplified, which I’m glad to see someone else has realized as well :-)

Here’s my proposal for reference: Proposal: Factory Initializers by rileytestut · Pull Request #247 · apple/swift-evolution · GitHub Originally I used the “factory” keyword, but I think your “indirect” keyword may be a better fit (since it has precedent in the language and is not limited to “just” being about factory initialization). To divide your proposal up into smaller pieces for review, maybe we could update my proposal to use your indirect keyword, and then start a separate topic/proposal for the remaining aspects of your proposal? I agree that splitting it into smaller chunks may be better for the process.

Let me know what you think!

Riley

On Jun 10, 2017, at 3:33 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This is a very interesting read.

Thanks you! I tried to make it as clear and detailed as possible. :slightly_smiling_face:

We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

I was writing the proposal and was just about to write `factory init`, when it occurred to me: enums already have a keyword that does something very similar. It seemed to me that an initializer that doesn't initialize the instance in-place, but returns a completely separate instance from somewhere else, is kinda "indirectly" initializing the instance. Plus, the already established keyword and its semantic would reduce the learning curve for this new feature and separate it from a single specific use case (the "factory method" pattern).

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

I think the `return` can be easily implemented first, while opening up an opportunity to later implement `indirect init`. The reason why I unified them was that the `return` idea on its own has very limited merit and could the thought of as a low-priority cosmetic enhancement. I wouldn't want it to be viewed that way because the primary purpose of that idea is to enable `indirect init` (which Cocoa and Cocoa Touch developers would be very happy about).

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

Very good point. The challenge is to correctly separate them, without losing context in their respective proposals and without bleeding the proposals into each other.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

I'd never send a pull request to swift-evolution without thoroughly discussing it here. I just though, if I'm going to write a whole proposal with examples and motivation, it would be easier to demonstrate it and discuss in with the community If I just went ahead and wrote the whole thing and sent the link. This way it would be clearer to the reader and the discussed changes would be accurately reflected by the commits I'd make to my proposal.

Original Message

On Jun 10, 2017, at 2:38 AM, Daryle Walker via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/master/proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed it wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

This is a very interesting read. We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Cool. I have reservations about idea #3, but we can tackle that another day. (Real life things beckon.) But suffice it to say that I now really, really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self` non-optional.
This would make `return nil` less out-of-place, like you said, while still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax, while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it to change the signature as well as remove any compiler assumptions about the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
So far, we've discussed two ways of interpreting `self = nil`, both of which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as counter-intuitive, but recall that `return nil` is just as much of a special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax because the initializer notionally has no return value. Personally, I have always disliked `return nil` in failable initializers for that reason, but I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because, in the case of a failable initializer, `return nil` continues to have the same meaning if we consider the return value of the initializer to be of type `Self?`. For that reason, I think your idea #2 is quite clever, and it would go a long way in making `return nil` a lot less odd. It also increases the expressivity of initializers because it allows one to set the value of self and also return in one statement, clearly demonstrating the intention that no other code in the initializer should be run before returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with initialization semantics, it provides more uniform syntax and it's a bit less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more cumbersome. Implicitly unwrapped optionals are a bit difficult, but this "variation" of it is much more restrictive then the normal ones, because unlike normal implicitly unwrapped optionals, this one cannot be accessed after being assigned nil (and it also cannot be indirectly assigned `nil`, because escaping `self` is not allowed before full initialization), so there is only one possible place it can be set to nil and that's directly in the initializer. This means that `self` can be safely treated as `inout Self` before being set to nil (and after being set to nil, it doesn't matter any more because you aren't allowed to access it, due to not being fully initialized).

I have to say, I don’t like either of these explanations at all. I think having a “special” IUO is a difficult sell; it is just conceptually too complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language wonkier because it currently has a parallel wonky feature in `return nil` seems like the wrong way to go. In addition, there’s nothing gained here that cannot be done with a defer statement; of course, defer statements might not be very elegant, but it would certainly be less wonky than inventing a new variation on an IUO to allow assignment of nil to self... For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic and the restrictions of `self as inout Self!` are imposed by already existing and well-understood initialization logic, so the provided guarantees don't really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
I think a good approach would be to have `self = nil` only mean `the initializer is going to fail` because if your type is ExpressibleByNilLiteral, it means that the `nil` of your type already carries the same meaning as if your type was not ExpressibleByNilLiteral and was an optional instead, so having a failable initializer doesn't really make sense in that case (since you could've initialized `self` to its own `nil` in case of failure). Still, some valid use cases may exist, so the natural (and quite intuitive) way to circumvent this would be to call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different thing in an initializer than it does in a function? Essentially, then, you’re creating your own variation on an implicitly unwrapped optional, where `self` is of type `inout Self?` for assignment in initializers only but not for any other purpose. Implicitly unwrapped optionals are hard to reason about, and having a variation on it would be even harder to understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however, I do think Greg is right that it would create more boilerplate than the current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
The type of `self` could remain `inout Self` inside the failable initializer. The ability to assign nil would be a compiler magic (much like `return nil` is compiler magic) that is meant to introduce uniformity to the initialization logic.

The idea is to define all different ways initialization can take place and expand them to be used uniformly on both `self` and all its members, as well as remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
  1. delegating initializer
  2. assigning to self
  3. returning nil

#1: The delegating initializer is pretty much perfect at this point, in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside failable initializers.

#3: The only thing that can be returned from an initializer is `nil`, which is compiler magic, so we can thing of it as a misnomer (because we aren't really **returning** anything).

If, for a second, we forget about potential factory initializers, returning anything from an initializer doesn't make much sense, because an initializer is conceptually meant to bring an existing object in memory to a type-specific valid state. This semantic was very explicitly in Objective-C with `[[MyType alloc] init]`. Especially since even syntactically, the initializer does not specify any return type, the idea of returning from an initializer is counter-intuitive both syntactically and semantically.

The actual *behavior* of `return nil` is very sensible, so the behavior, I imagine `self = nil`, would largely mean the same (except not needed to return immediately and allowing non-self-accessing code to be executed before return). Being able to assign `nil` to a non-optional (ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to initialize self to nil? That is what `self = nil` means if `self` is of type `inout Self`. If `self` is of type `inout Self` and Self is not ExpressibleByNilLiteral, then it must be an error to assign nil to self. Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to initialize an object in-place and doesn't look like it should return anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init` syntax could completely flip this logic, but making the initializer essentially a static function that returns an object. In this case the initializer could be made to specify the return type (that is the supertype of all possible factory-created objects) and assigning to self would be forbidden because there is not self yet:

extension MyProtocol {

  public factory init(weCool: Bool) -> MyProtocol {
    self = MyImpl() // error: cannot assign to `self` in a factory initializer
    self.init(...) // error: cannot make a delegating initializer call in a factory initializer
    if weCool {
      return MyCoolImpl()
    } else {
      return MyUncoolImpl()
    }
  }

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2 (as in `self.member = value`), which could be extended in a non-factory initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while giving a more reliable performance guarantee that this member will not be copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

If `self` is not of type `inout Self?`, then what is the type of `self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms to `ExpressibleByNilLiteral`, in which case you are able to assign `self = nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped optionals are no longer their own type, I’m not sure that’s possible. But even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self` would have to be of type `inout Self?`–which is intriguing but potentially more boilerplatey than the status quo.
On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and since `self` can only be initialized once, this would mean that after `self = nil`, you won't be allowed to access `self` in your initializer at all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to treat `self` as `inout Self?`, because the only place it can be `nil` is the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com <mailto:gparker@apple.com>> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable initializers (essentially making `self` look like `inout Self?` instead of `inout Self` with magical `return nil`), so that all initializers uniformly can be written in `self = ...` form for clarity and convenience purposes. This should, theoretically, be nothing but a `defer { return nil }` type of rewrite, so I don't see any major difficulties implementing this. This is especially useful for failable-initializing enums where the main switch simply assigns to self in all cases and the rest of the initializer does some post-processing.

I don't see how to avoid source incompatibility and uglification of failable initializer implementations here. Allowing `self = nil` inside a failable initializer would require `self` to be an optional. That in turn would require every use of `self` in the initializer to be nil-checked or forced. I don't think that loss everywhere outweighs the gain of `self = nil` in some places.

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler

_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

Awesome! Updated my proposal to include what I believed to be the relevant portions of your indirect initializer idea. Let me know if there’s anything I missed or should change :-)

···

On Jun 10, 2017, at 12:43 PM, Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

Hi, Riley!

I think that's a great idea! We can merge the second part of my proposal (the `indirect init`) into your one and refine and consolidate the prerequisite proposal (about returning from `init` and possibly in-place member initializers) and bunch them up into a proposal cluster (the way swift coders did).
Feel free to tear out any chunks from my proposal, while I think about a more in-depth rationale about revamping initialization syntax. :slightly_smiling_face:

On Jun 10, 2017, at 8:36 PM, Riley Testut <rileytestut@gmail.com <mailto:rileytestut@gmail.com>> wrote:

Hi Gor :wave:

I’m very much in fan of a unified initialization syntax. I submitted my own proposal for factory initializers a while back, but since it wasn’t a focus of Swift 3 or 4 I haven’t followed up on it recently. In the time since last working on it, I came to my own conclusion that rather than focusing on factory initialization, the overall initialization process should be simplified, which I’m glad to see someone else has realized as well :-)

Here’s my proposal for reference: Proposal: Factory Initializers by rileytestut · Pull Request #247 · apple/swift-evolution · GitHub Originally I used the “factory” keyword, but I think your “indirect” keyword may be a better fit (since it has precedent in the language and is not limited to “just” being about factory initialization). To divide your proposal up into smaller pieces for review, maybe we could update my proposal to use your indirect keyword, and then start a separate topic/proposal for the remaining aspects of your proposal? I agree that splitting it into smaller chunks may be better for the process.

Let me know what you think!

Riley

On Jun 10, 2017, at 3:33 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This is a very interesting read.

Thanks you! I tried to make it as clear and detailed as possible. :slightly_smiling_face:

We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

I was writing the proposal and was just about to write `factory init`, when it occurred to me: enums already have a keyword that does something very similar. It seemed to me that an initializer that doesn't initialize the instance in-place, but returns a completely separate instance from somewhere else, is kinda "indirectly" initializing the instance. Plus, the already established keyword and its semantic would reduce the learning curve for this new feature and separate it from a single specific use case (the "factory method" pattern).

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

I think the `return` can be easily implemented first, while opening up an opportunity to later implement `indirect init`. The reason why I unified them was that the `return` idea on its own has very limited merit and could the thought of as a low-priority cosmetic enhancement. I wouldn't want it to be viewed that way because the primary purpose of that idea is to enable `indirect init` (which Cocoa and Cocoa Touch developers would be very happy about).

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

Very good point. The challenge is to correctly separate them, without losing context in their respective proposals and without bleeding the proposals into each other.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

I'd never send a pull request to swift-evolution without thoroughly discussing it here. I just though, if I'm going to write a whole proposal with examples and motivation, it would be easier to demonstrate it and discuss in with the community If I just went ahead and wrote the whole thing and sent the link. This way it would be clearer to the reader and the discussed changes would be accurately reflected by the commits I'd make to my proposal.

Original Message

On Jun 10, 2017, at 2:38 AM, Daryle Walker via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/master/proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed it wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

This is a very interesting read. We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Cool. I have reservations about idea #3, but we can tackle that another day. (Real life things beckon.) But suffice it to say that I now really, really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self` non-optional.
This would make `return nil` less out-of-place, like you said, while still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax, while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it to change the signature as well as remove any compiler assumptions about the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
So far, we've discussed two ways of interpreting `self = nil`, both of which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as counter-intuitive, but recall that `return nil` is just as much of a special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax because the initializer notionally has no return value. Personally, I have always disliked `return nil` in failable initializers for that reason, but I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because, in the case of a failable initializer, `return nil` continues to have the same meaning if we consider the return value of the initializer to be of type `Self?`. For that reason, I think your idea #2 is quite clever, and it would go a long way in making `return nil` a lot less odd. It also increases the expressivity of initializers because it allows one to set the value of self and also return in one statement, clearly demonstrating the intention that no other code in the initializer should be run before returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with initialization semantics, it provides more uniform syntax and it's a bit less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more cumbersome. Implicitly unwrapped optionals are a bit difficult, but this "variation" of it is much more restrictive then the normal ones, because unlike normal implicitly unwrapped optionals, this one cannot be accessed after being assigned nil (and it also cannot be indirectly assigned `nil`, because escaping `self` is not allowed before full initialization), so there is only one possible place it can be set to nil and that's directly in the initializer. This means that `self` can be safely treated as `inout Self` before being set to nil (and after being set to nil, it doesn't matter any more because you aren't allowed to access it, due to not being fully initialized).

I have to say, I don’t like either of these explanations at all. I think having a “special” IUO is a difficult sell; it is just conceptually too complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language wonkier because it currently has a parallel wonky feature in `return nil` seems like the wrong way to go. In addition, there’s nothing gained here that cannot be done with a defer statement; of course, defer statements might not be very elegant, but it would certainly be less wonky than inventing a new variation on an IUO to allow assignment of nil to self... For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic and the restrictions of `self as inout Self!` are imposed by already existing and well-understood initialization logic, so the provided guarantees don't really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
I think a good approach would be to have `self = nil` only mean `the initializer is going to fail` because if your type is ExpressibleByNilLiteral, it means that the `nil` of your type already carries the same meaning as if your type was not ExpressibleByNilLiteral and was an optional instead, so having a failable initializer doesn't really make sense in that case (since you could've initialized `self` to its own `nil` in case of failure). Still, some valid use cases may exist, so the natural (and quite intuitive) way to circumvent this would be to call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different thing in an initializer than it does in a function? Essentially, then, you’re creating your own variation on an implicitly unwrapped optional, where `self` is of type `inout Self?` for assignment in initializers only but not for any other purpose. Implicitly unwrapped optionals are hard to reason about, and having a variation on it would be even harder to understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however, I do think Greg is right that it would create more boilerplate than the current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
The type of `self` could remain `inout Self` inside the failable initializer. The ability to assign nil would be a compiler magic (much like `return nil` is compiler magic) that is meant to introduce uniformity to the initialization logic.

The idea is to define all different ways initialization can take place and expand them to be used uniformly on both `self` and all its members, as well as remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
  1. delegating initializer
  2. assigning to self
  3. returning nil

#1: The delegating initializer is pretty much perfect at this point, in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside failable initializers.

#3: The only thing that can be returned from an initializer is `nil`, which is compiler magic, so we can thing of it as a misnomer (because we aren't really **returning** anything).

If, for a second, we forget about potential factory initializers, returning anything from an initializer doesn't make much sense, because an initializer is conceptually meant to bring an existing object in memory to a type-specific valid state. This semantic was very explicitly in Objective-C with `[[MyType alloc] init]`. Especially since even syntactically, the initializer does not specify any return type, the idea of returning from an initializer is counter-intuitive both syntactically and semantically.

The actual *behavior* of `return nil` is very sensible, so the behavior, I imagine `self = nil`, would largely mean the same (except not needed to return immediately and allowing non-self-accessing code to be executed before return). Being able to assign `nil` to a non-optional (ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to initialize self to nil? That is what `self = nil` means if `self` is of type `inout Self`. If `self` is of type `inout Self` and Self is not ExpressibleByNilLiteral, then it must be an error to assign nil to self. Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to initialize an object in-place and doesn't look like it should return anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init` syntax could completely flip this logic, but making the initializer essentially a static function that returns an object. In this case the initializer could be made to specify the return type (that is the supertype of all possible factory-created objects) and assigning to self would be forbidden because there is not self yet:

extension MyProtocol {

  public factory init(weCool: Bool) -> MyProtocol {
    self = MyImpl() // error: cannot assign to `self` in a factory initializer
    self.init(...) // error: cannot make a delegating initializer call in a factory initializer
    if weCool {
      return MyCoolImpl()
    } else {
      return MyUncoolImpl()
    }
  }

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2 (as in `self.member = value`), which could be extended in a non-factory initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while giving a more reliable performance guarantee that this member will not be copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

If `self` is not of type `inout Self?`, then what is the type of `self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms to `ExpressibleByNilLiteral`, in which case you are able to assign `self = nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped optionals are no longer their own type, I’m not sure that’s possible. But even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self` would have to be of type `inout Self?`–which is intriguing but potentially more boilerplatey than the status quo.
On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and since `self` can only be initialized once, this would mean that after `self = nil`, you won't be allowed to access `self` in your initializer at all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to treat `self` as `inout Self?`, because the only place it can be `nil` is the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com <mailto:gparker@apple.com>> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable initializers (essentially making `self` look like `inout Self?` instead of `inout Self` with magical `return nil`), so that all initializers uniformly can be written in `self = ...` form for clarity and convenience purposes. This should, theoretically, be nothing but a `defer { return nil }` type of rewrite, so I don't see any major difficulties implementing this. This is especially useful for failable-initializing enums where the main switch simply assigns to self in all cases and the rest of the initializer does some post-processing.

I don't see how to avoid source incompatibility and uglification of failable initializer implementations here. Allowing `self = nil` inside a failable initializer would require `self` to be an optional. That in turn would require every use of `self` in the initializer to be nil-checked or forced. I don't think that loss everywhere outweighs the gain of `self = nil` in some places.

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler

_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

Looks good, but I have a few thoughts on it:

* I think indirect initializers *shoud* be overridable, but only by other indirect initializers. This will allow subclasses of the factory to expand the factory method by adding new possible instances to return.
* You did not include the specification of implementation details that I provided as well as C/Objective-C interoperability changes.
* The proposal is formulated more like a personal opinion, rather then a formal specification. It sounds like a personal letter. I'd recommend writing it similarly as you'd write a wikipedia page.

···

On Jun 11, 2017, at 1:12 AM, Riley Testut <rileytestut@gmail.com> wrote:

Awesome! Updated my proposal to include what I believed to be the relevant portions of your indirect initializer idea. Let me know if there’s anything I missed or should change :-)

https://github.com/rileytestut/swift-evolution/blob/master/proposals/NNNN-factory-initializers.md

On Jun 10, 2017, at 12:43 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:

Hi, Riley!

I think that's a great idea! We can merge the second part of my proposal (the `indirect init`) into your one and refine and consolidate the prerequisite proposal (about returning from `init` and possibly in-place member initializers) and bunch them up into a proposal cluster (the way swift coders did).
Feel free to tear out any chunks from my proposal, while I think about a more in-depth rationale about revamping initialization syntax. :slightly_smiling_face:

On Jun 10, 2017, at 8:36 PM, Riley Testut <rileytestut@gmail.com <mailto:rileytestut@gmail.com>> wrote:

Hi Gor :wave:

I’m very much in fan of a unified initialization syntax. I submitted my own proposal for factory initializers a while back, but since it wasn’t a focus of Swift 3 or 4 I haven’t followed up on it recently. In the time since last working on it, I came to my own conclusion that rather than focusing on factory initialization, the overall initialization process should be simplified, which I’m glad to see someone else has realized as well :-)

Here’s my proposal for reference: Proposal: Factory Initializers by rileytestut · Pull Request #247 · apple/swift-evolution · GitHub Originally I used the “factory” keyword, but I think your “indirect” keyword may be a better fit (since it has precedent in the language and is not limited to “just” being about factory initialization). To divide your proposal up into smaller pieces for review, maybe we could update my proposal to use your indirect keyword, and then start a separate topic/proposal for the remaining aspects of your proposal? I agree that splitting it into smaller chunks may be better for the process.

Let me know what you think!

Riley

On Jun 10, 2017, at 3:33 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This is a very interesting read.

Thanks you! I tried to make it as clear and detailed as possible. :slightly_smiling_face:

We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

I was writing the proposal and was just about to write `factory init`, when it occurred to me: enums already have a keyword that does something very similar. It seemed to me that an initializer that doesn't initialize the instance in-place, but returns a completely separate instance from somewhere else, is kinda "indirectly" initializing the instance. Plus, the already established keyword and its semantic would reduce the learning curve for this new feature and separate it from a single specific use case (the "factory method" pattern).

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

I think the `return` can be easily implemented first, while opening up an opportunity to later implement `indirect init`. The reason why I unified them was that the `return` idea on its own has very limited merit and could the thought of as a low-priority cosmetic enhancement. I wouldn't want it to be viewed that way because the primary purpose of that idea is to enable `indirect init` (which Cocoa and Cocoa Touch developers would be very happy about).

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

Very good point. The challenge is to correctly separate them, without losing context in their respective proposals and without bleeding the proposals into each other.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

I'd never send a pull request to swift-evolution without thoroughly discussing it here. I just though, if I'm going to write a whole proposal with examples and motivation, it would be easier to demonstrate it and discuss in with the community If I just went ahead and wrote the whole thing and sent the link. This way it would be clearer to the reader and the discussed changes would be accurately reflected by the commits I'd make to my proposal.

Original Message

On Jun 10, 2017, at 2:38 AM, Daryle Walker via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/master/proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed it wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

This is a very interesting read. We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Cool. I have reservations about idea #3, but we can tackle that another day. (Real life things beckon.) But suffice it to say that I now really, really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self` non-optional.
This would make `return nil` less out-of-place, like you said, while still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax, while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it to change the signature as well as remove any compiler assumptions about the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
So far, we've discussed two ways of interpreting `self = nil`, both of which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as counter-intuitive, but recall that `return nil` is just as much of a special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax because the initializer notionally has no return value. Personally, I have always disliked `return nil` in failable initializers for that reason, but I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because, in the case of a failable initializer, `return nil` continues to have the same meaning if we consider the return value of the initializer to be of type `Self?`. For that reason, I think your idea #2 is quite clever, and it would go a long way in making `return nil` a lot less odd. It also increases the expressivity of initializers because it allows one to set the value of self and also return in one statement, clearly demonstrating the intention that no other code in the initializer should be run before returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with initialization semantics, it provides more uniform syntax and it's a bit less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more cumbersome. Implicitly unwrapped optionals are a bit difficult, but this "variation" of it is much more restrictive then the normal ones, because unlike normal implicitly unwrapped optionals, this one cannot be accessed after being assigned nil (and it also cannot be indirectly assigned `nil`, because escaping `self` is not allowed before full initialization), so there is only one possible place it can be set to nil and that's directly in the initializer. This means that `self` can be safely treated as `inout Self` before being set to nil (and after being set to nil, it doesn't matter any more because you aren't allowed to access it, due to not being fully initialized).

I have to say, I don’t like either of these explanations at all. I think having a “special” IUO is a difficult sell; it is just conceptually too complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language wonkier because it currently has a parallel wonky feature in `return nil` seems like the wrong way to go. In addition, there’s nothing gained here that cannot be done with a defer statement; of course, defer statements might not be very elegant, but it would certainly be less wonky than inventing a new variation on an IUO to allow assignment of nil to self... For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic and the restrictions of `self as inout Self!` are imposed by already existing and well-understood initialization logic, so the provided guarantees don't really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
I think a good approach would be to have `self = nil` only mean `the initializer is going to fail` because if your type is ExpressibleByNilLiteral, it means that the `nil` of your type already carries the same meaning as if your type was not ExpressibleByNilLiteral and was an optional instead, so having a failable initializer doesn't really make sense in that case (since you could've initialized `self` to its own `nil` in case of failure). Still, some valid use cases may exist, so the natural (and quite intuitive) way to circumvent this would be to call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different thing in an initializer than it does in a function? Essentially, then, you’re creating your own variation on an implicitly unwrapped optional, where `self` is of type `inout Self?` for assignment in initializers only but not for any other purpose. Implicitly unwrapped optionals are hard to reason about, and having a variation on it would be even harder to understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however, I do think Greg is right that it would create more boilerplate than the current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
The type of `self` could remain `inout Self` inside the failable initializer. The ability to assign nil would be a compiler magic (much like `return nil` is compiler magic) that is meant to introduce uniformity to the initialization logic.

The idea is to define all different ways initialization can take place and expand them to be used uniformly on both `self` and all its members, as well as remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
  1. delegating initializer
  2. assigning to self
  3. returning nil

#1: The delegating initializer is pretty much perfect at this point, in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside failable initializers.

#3: The only thing that can be returned from an initializer is `nil`, which is compiler magic, so we can thing of it as a misnomer (because we aren't really **returning** anything).

If, for a second, we forget about potential factory initializers, returning anything from an initializer doesn't make much sense, because an initializer is conceptually meant to bring an existing object in memory to a type-specific valid state. This semantic was very explicitly in Objective-C with `[[MyType alloc] init]`. Especially since even syntactically, the initializer does not specify any return type, the idea of returning from an initializer is counter-intuitive both syntactically and semantically.

The actual *behavior* of `return nil` is very sensible, so the behavior, I imagine `self = nil`, would largely mean the same (except not needed to return immediately and allowing non-self-accessing code to be executed before return). Being able to assign `nil` to a non-optional (ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to initialize self to nil? That is what `self = nil` means if `self` is of type `inout Self`. If `self` is of type `inout Self` and Self is not ExpressibleByNilLiteral, then it must be an error to assign nil to self. Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to initialize an object in-place and doesn't look like it should return anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init` syntax could completely flip this logic, but making the initializer essentially a static function that returns an object. In this case the initializer could be made to specify the return type (that is the supertype of all possible factory-created objects) and assigning to self would be forbidden because there is not self yet:

extension MyProtocol {

  public factory init(weCool: Bool) -> MyProtocol {
    self = MyImpl() // error: cannot assign to `self` in a factory initializer
    self.init(...) // error: cannot make a delegating initializer call in a factory initializer
    if weCool {
      return MyCoolImpl()
    } else {
      return MyUncoolImpl()
    }
  }

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2 (as in `self.member = value`), which could be extended in a non-factory initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while giving a more reliable performance guarantee that this member will not be copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

If `self` is not of type `inout Self?`, then what is the type of `self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms to `ExpressibleByNilLiteral`, in which case you are able to assign `self = nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped optionals are no longer their own type, I’m not sure that’s possible. But even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self` would have to be of type `inout Self?`–which is intriguing but potentially more boilerplatey than the status quo.
On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and since `self` can only be initialized once, this would mean that after `self = nil`, you won't be allowed to access `self` in your initializer at all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to treat `self` as `inout Self?`, because the only place it can be `nil` is the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com <mailto:gparker@apple.com>> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable initializers (essentially making `self` look like `inout Self?` instead of `inout Self` with magical `return nil`), so that all initializers uniformly can be written in `self = ...` form for clarity and convenience purposes. This should, theoretically, be nothing but a `defer { return nil }` type of rewrite, so I don't see any major difficulties implementing this. This is especially useful for failable-initializing enums where the main switch simply assigns to self in all cases and the rest of the initializer does some post-processing.

I don't see how to avoid source incompatibility and uglification of failable initializer implementations here. Allowing `self = nil` inside a failable initializer would require `self` to be an optional. That in turn would require every use of `self` in the initializer to be nil-checked or forced. I don't think that loss everywhere outweighs the gain of `self = nil` in some places.

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler

_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

Hey how about a new company called
Kernal*saun*$eeders*=ultimatetruecode.ORG
I have the I dream of the kings of live script support
No one can top us

Awesome! Updated my proposal to include what I believed to be the relevant portions of your indirect initializer idea. Let me know if there’s anything I missed or should change :-)

···

Sent from my iPhone
On Jun 10, 2017, at 3:12 PM, Riley Testut via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 10, 2017, at 12:43 PM, Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

Hi, Riley!

I think that's a great idea! We can merge the second part of my proposal (the `indirect init`) into your one and refine and consolidate the prerequisite proposal (about returning from `init` and possibly in-place member initializers) and bunch them up into a proposal cluster (the way swift coders did).
Feel free to tear out any chunks from my proposal, while I think about a more in-depth rationale about revamping initialization syntax. :slightly_smiling_face:

On Jun 10, 2017, at 8:36 PM, Riley Testut <rileytestut@gmail.com> wrote:

Hi Gor :wave:

I’m very much in fan of a unified initialization syntax. I submitted my own proposal for factory initializers a while back, but since it wasn’t a focus of Swift 3 or 4 I haven’t followed up on it recently. In the time since last working on it, I came to my own conclusion that rather than focusing on factory initialization, the overall initialization process should be simplified, which I’m glad to see someone else has realized as well :-)

Here’s my proposal for reference: Proposal: Factory Initializers by rileytestut · Pull Request #247 · apple/swift-evolution · GitHub Originally I used the “factory” keyword, but I think your “indirect” keyword may be a better fit (since it has precedent in the language and is not limited to “just” being about factory initialization). To divide your proposal up into smaller pieces for review, maybe we could update my proposal to use your indirect keyword, and then start a separate topic/proposal for the remaining aspects of your proposal? I agree that splitting it into smaller chunks may be better for the process.

Let me know what you think!

Riley

On Jun 10, 2017, at 3:33 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org> wrote:

This is a very interesting read.

Thanks you! I tried to make it as clear and detailed as possible. :slightly_smiling_face:

We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

I was writing the proposal and was just about to write `factory init`, when it occurred to me: enums already have a keyword that does something very similar. It seemed to me that an initializer that doesn't initialize the instance in-place, but returns a completely separate instance from somewhere else, is kinda "indirectly" initializing the instance. Plus, the already established keyword and its semantic would reduce the learning curve for this new feature and separate it from a single specific use case (the "factory method" pattern).

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

I think the `return` can be easily implemented first, while opening up an opportunity to later implement `indirect init`. The reason why I unified them was that the `return` idea on its own has very limited merit and could the thought of as a low-priority cosmetic enhancement. I wouldn't want it to be viewed that way because the primary purpose of that idea is to enable `indirect init` (which Cocoa and Cocoa Touch developers would be very happy about).

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

Very good point. The challenge is to correctly separate them, without losing context in their respective proposals and without bleeding the proposals into each other.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

I'd never send a pull request to swift-evolution without thoroughly discussing it here. I just though, if I'm going to write a whole proposal with examples and motivation, it would be easier to demonstrate it and discuss in with the community If I just went ahead and wrote the whole thing and sent the link. This way it would be clearer to the reader and the discussed changes would be accurately reflected by the commits I'd make to my proposal.

Original Message

On Jun 10, 2017, at 2:38 AM, Daryle Walker via swift-evolution <swift-evolution@swift.org> wrote:

On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <gor@gyolchanyan.com> wrote:
Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/master/proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed it wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

This is a very interesting read. We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Cool. I have reservations about idea #3, but we can tackle that another day. (Real life things beckon.) But suffice it to say that I now really, really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self` non-optional.
This would make `return nil` less out-of-place, like you said, while still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax, while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it to change the signature as well as remove any compiler assumptions about the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:
So far, we've discussed two ways of interpreting `self = nil`, both of which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as counter-intuitive, but recall that `return nil` is just as much of a special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax because the initializer notionally has no return value. Personally, I have always disliked `return nil` in failable initializers for that reason, but I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because, in the case of a failable initializer, `return nil` continues to have the same meaning if we consider the return value of the initializer to be of type `Self?`. For that reason, I think your idea #2 is quite clever, and it would go a long way in making `return nil` a lot less odd. It also increases the expressivity of initializers because it allows one to set the value of self and also return in one statement, clearly demonstrating the intention that no other code in the initializer should be run before returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with initialization semantics, it provides more uniform syntax and it's a bit less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more cumbersome. Implicitly unwrapped optionals are a bit difficult, but this "variation" of it is much more restrictive then the normal ones, because unlike normal implicitly unwrapped optionals, this one cannot be accessed after being assigned nil (and it also cannot be indirectly assigned `nil`, because escaping `self` is not allowed before full initialization), so there is only one possible place it can be set to nil and that's directly in the initializer. This means that `self` can be safely treated as `inout Self` before being set to nil (and after being set to nil, it doesn't matter any more because you aren't allowed to access it, due to not being fully initialized).

I have to say, I don’t like either of these explanations at all. I think having a “special” IUO is a difficult sell; it is just conceptually too complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language wonkier because it currently has a parallel wonky feature in `return nil` seems like the wrong way to go. In addition, there’s nothing gained here that cannot be done with a defer statement; of course, defer statements might not be very elegant, but it would certainly be less wonky than inventing a new variation on an IUO to allow assignment of nil to self... For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic and the restrictions of `self as inout Self!` are imposed by already existing and well-understood initialization logic, so the provided guarantees don't really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:
I think a good approach would be to have `self = nil` only mean `the initializer is going to fail` because if your type is ExpressibleByNilLiteral, it means that the `nil` of your type already carries the same meaning as if your type was not ExpressibleByNilLiteral and was an optional instead, so having a failable initializer doesn't really make sense in that case (since you could've initialized `self` to its own `nil` in case of failure). Still, some valid use cases may exist, so the natural (and quite intuitive) way to circumvent this would be to call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different thing in an initializer than it does in a function? Essentially, then, you’re creating your own variation on an implicitly unwrapped optional, where `self` is of type `inout Self?` for assignment in initializers only but not for any other purpose. Implicitly unwrapped optionals are hard to reason about, and having a variation on it would be even harder to understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however, I do think Greg is right that it would create more boilerplate than the current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:
The type of `self` could remain `inout Self` inside the failable initializer. The ability to assign nil would be a compiler magic (much like `return nil` is compiler magic) that is meant to introduce uniformity to the initialization logic.

The idea is to define all different ways initialization can take place and expand them to be used uniformly on both `self` and all its members, as well as remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
  1. delegating initializer
  2. assigning to self
  3. returning nil

#1: The delegating initializer is pretty much perfect at this point, in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside failable initializers.

#3: The only thing that can be returned from an initializer is `nil`, which is compiler magic, so we can thing of it as a misnomer (because we aren't really **returning** anything).

If, for a second, we forget about potential factory initializers, returning anything from an initializer doesn't make much sense, because an initializer is conceptually meant to bring an existing object in memory to a type-specific valid state. This semantic was very explicitly in Objective-C with `[[MyType alloc] init]`. Especially since even syntactically, the initializer does not specify any return type, the idea of returning from an initializer is counter-intuitive both syntactically and semantically.

The actual *behavior* of `return nil` is very sensible, so the behavior, I imagine `self = nil`, would largely mean the same (except not needed to return immediately and allowing non-self-accessing code to be executed before return). Being able to assign `nil` to a non-optional (ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to initialize self to nil? That is what `self = nil` means if `self` is of type `inout Self`. If `self` is of type `inout Self` and Self is not ExpressibleByNilLiteral, then it must be an error to assign nil to self. Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to initialize an object in-place and doesn't look like it should return anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init` syntax could completely flip this logic, but making the initializer essentially a static function that returns an object. In this case the initializer could be made to specify the return type (that is the supertype of all possible factory-created objects) and assigning to self would be forbidden because there is not self yet:

extension MyProtocol {

  public factory init(weCool: Bool) -> MyProtocol {
    self = MyImpl() // error: cannot assign to `self` in a factory initializer
    self.init(...) // error: cannot make a delegating initializer call in a factory initializer
    if weCool {
      return MyCoolImpl()
    } else {
      return MyUncoolImpl()
    }
  }

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2 (as in `self.member = value`), which could be extended in a non-factory initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while giving a more reliable performance guarantee that this member will not be copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

If `self` is not of type `inout Self?`, then what is the type of `self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms to `ExpressibleByNilLiteral`, in which case you are able to assign `self = nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped optionals are no longer their own type, I’m not sure that’s possible. But even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self` would have to be of type `inout Self?`–which is intriguing but potentially more boilerplatey than the status quo.

On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org> wrote:
Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and since `self` can only be initialized once, this would mean that after `self = nil`, you won't be allowed to access `self` in your initializer at all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to treat `self` as `inout Self?`, because the only place it can be `nil` is the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable initializers (essentially making `self` look like `inout Self?` instead of `inout Self` with magical `return nil`), so that all initializers uniformly can be written in `self = ...` form for clarity and convenience purposes. This should, theoretically, be nothing but a `defer { return nil }` type of rewrite, so I don't see any major difficulties implementing this. This is especially useful for failable-initializing enums where the main switch simply assigns to self in all cases and the rest of the initializer does some post-processing.

I don't see how to avoid source incompatibility and uglification of failable initializer implementations here. Allowing `self = nil` inside a failable initializer would require `self` to be an optional. That in turn would require every use of `self` in the initializer to be nil-checked or forced. I don't think that loss everywhere outweighs the gain of `self = nil` in some places.

--
Greg Parker gparker@apple.com Runtime Wrangler

_______________________________________________
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

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

The proposal is looking good to me. :) It will also enable easy support for custom views using XIBs in iOS development without unnecessary view nesting.

For instance the function from this example ios - Loading a XIB file to a UIView Swift - Stack Overflow could be used directly inside an init:

class MyView : UIView {
     
      indirect init() {
            return MyView.instantiateFromXib()
            // Or after SR-0068
            return Self.instantiateFromXib()
      }
}
There is still one little thing that bothers me, it might be a little bit confusing to have two different meanings of indirect on enums.

indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)
     
    // This might makes no sense, but it would still be possible after
    // this proposal.
    indirect init(other: ArithmeticExpression) {
       return other
    }
     
    // Furthermore if the keyboard is applied to the enum
    // directly all other `indirect` uses are inferred.
    // Will this be implicitly `indirect` because of the previous fact?
    init() { … }
}

···

--
Adrian Zubarev
Sent with Airmail

Am 11. Juni 2017 um 00:38:56, Riley Testut via swift-evolution (swift-evolution@swift.org) schrieb:

Awesome! Updated my proposal to include what I believed to be the relevant portions of your indirect initializer idea. Let me know if there’s anything I missed or should change :-)

On Jun 10, 2017, at 12:43 PM, Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

Hi, Riley!

I think that's a great idea! We can merge the second part of my proposal (the `indirect init`) into your one and refine and consolidate the prerequisite proposal (about returning from `init` and possibly in-place member initializers) and bunch them up into a proposal cluster (the way swift coders did).
Feel free to tear out any chunks from my proposal, while I think about a more in-depth rationale about revamping initialization syntax. :slightly_smiling_face:

On Jun 10, 2017, at 8:36 PM, Riley Testut <rileytestut@gmail.com> wrote:

Hi Gor :wave:

I’m very much in fan of a unified initialization syntax. I submitted my own proposal for factory initializers a while back, but since it wasn’t a focus of Swift 3 or 4 I haven’t followed up on it recently. In the time since last working on it, I came to my own conclusion that rather than focusing on factory initialization, the overall initialization process should be simplified, which I’m glad to see someone else has realized as well :-)

Here’s my proposal for reference: Proposal: Factory Initializers by rileytestut · Pull Request #247 · apple/swift-evolution · GitHub Originally I used the “factory” keyword, but I think your “indirect” keyword may be a better fit (since it has precedent in the language and is not limited to “just” being about factory initialization). To divide your proposal up into smaller pieces for review, maybe we could update my proposal to use your indirect keyword, and then start a separate topic/proposal for the remaining aspects of your proposal? I agree that splitting it into smaller chunks may be better for the process.

Let me know what you think!

Riley

On Jun 10, 2017, at 3:33 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org> wrote:

This is a very interesting read.

Thanks you! I tried to make it as clear and detailed as possible. :slightly_smiling_face:

We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

I was writing the proposal and was just about to write `factory init`, when it occurred to me: enums already have a keyword that does something very similar. It seemed to me that an initializer that doesn't initialize the instance in-place, but returns a completely separate instance from somewhere else, is kinda "indirectly" initializing the instance. Plus, the already established keyword and its semantic would reduce the learning curve for this new feature and separate it from a single specific use case (the "factory method" pattern).

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

I think the `return` can be easily implemented first, while opening up an opportunity to later implement `indirect init`. The reason why I unified them was that the `return` idea on its own has very limited merit and could the thought of as a low-priority cosmetic enhancement. I wouldn't want it to be viewed that way because the primary purpose of that idea is to enable `indirect init` (which Cocoa and Cocoa Touch developers would be very happy about).

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

Very good point. The challenge is to correctly separate them, without losing context in their respective proposals and without bleeding the proposals into each other.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

I'd never send a pull request to swift-evolution without thoroughly discussing it here. I just though, if I'm going to write a whole proposal with examples and motivation, it would be easier to demonstrate it and discuss in with the community If I just went ahead and wrote the whole thing and sent the link. This way it would be clearer to the reader and the discussed changes would be accurately reflected by the commits I'd make to my proposal.

Original Message

On Jun 10, 2017, at 2:38 AM, Daryle Walker via swift-evolution <swift-evolution@swift.org> wrote:

On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <gor@gyolchanyan.com> wrote:
Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/master/proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed it wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

This is a very interesting read. We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Cool. I have reservations about idea #3, but we can tackle that another day. (Real life things beckon.) But suffice it to say that I now really, really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:
You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self` non-optional.
This would make `return nil` less out-of-place, like you said, while still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax, while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it to change the signature as well as remove any compiler assumptions about the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:
So far, we've discussed two ways of interpreting `self = nil`, both of which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as counter-intuitive, but recall that `return nil` is just as much of a special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax because the initializer notionally has no return value. Personally, I have always disliked `return nil` in failable initializers for that reason, but I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because, in the case of a failable initializer, `return nil` continues to have the same meaning if we consider the return value of the initializer to be of type `Self?`. For that reason, I think your idea #2 is quite clever, and it would go a long way in making `return nil` a lot less odd. It also increases the expressivity of initializers because it allows one to set the value of self and also return in one statement, clearly demonstrating the intention that no other code in the initializer should be run before returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with initialization semantics, it provides more uniform syntax and it's a bit less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more cumbersome. Implicitly unwrapped optionals are a bit difficult, but this "variation" of it is much more restrictive then the normal ones, because unlike normal implicitly unwrapped optionals, this one cannot be accessed after being assigned nil (and it also cannot be indirectly assigned `nil`, because escaping `self` is not allowed before full initialization), so there is only one possible place it can be set to nil and that's directly in the initializer. This means that `self` can be safely treated as `inout Self` before being set to nil (and after being set to nil, it doesn't matter any more because you aren't allowed to access it, due to not being fully initialized).

I have to say, I don’t like either of these explanations at all. I think having a “special” IUO is a difficult sell; it is just conceptually too complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language wonkier because it currently has a parallel wonky feature in `return nil` seems like the wrong way to go. In addition, there’s nothing gained here that cannot be done with a defer statement; of course, defer statements might not be very elegant, but it would certainly be less wonky than inventing a new variation on an IUO to allow assignment of nil to self... For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic and the restrictions of `self as inout Self!` are imposed by already existing and well-understood initialization logic, so the provided guarantees don't really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:
I think a good approach would be to have `self = nil` only mean `the initializer is going to fail` because if your type is ExpressibleByNilLiteral, it means that the `nil` of your type already carries the same meaning as if your type was not ExpressibleByNilLiteral and was an optional instead, so having a failable initializer doesn't really make sense in that case (since you could've initialized `self` to its own `nil` in case of failure). Still, some valid use cases may exist, so the natural (and quite intuitive) way to circumvent this would be to call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different thing in an initializer than it does in a function? Essentially, then, you’re creating your own variation on an implicitly unwrapped optional, where `self` is of type `inout Self?` for assignment in initializers only but not for any other purpose. Implicitly unwrapped optionals are hard to reason about, and having a variation on it would be even harder to understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however, I do think Greg is right that it would create more boilerplate than the current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:
The type of `self` could remain `inout Self` inside the failable initializer. The ability to assign nil would be a compiler magic (much like `return nil` is compiler magic) that is meant to introduce uniformity to the initialization logic.

The idea is to define all different ways initialization can take place and expand them to be used uniformly on both `self` and all its members, as well as remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
1. delegating initializer
2. assigning to self
3. returning nil

#1: The delegating initializer is pretty much perfect at this point, in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside failable initializers.

#3: The only thing that can be returned from an initializer is `nil`, which is compiler magic, so we can thing of it as a misnomer (because we aren't really **returning** anything).

If, for a second, we forget about potential factory initializers, returning anything from an initializer doesn't make much sense, because an initializer is conceptually meant to bring an existing object in memory to a type-specific valid state. This semantic was very explicitly in Objective-C with `[[MyType alloc] init]`. Especially since even syntactically, the initializer does not specify any return type, the idea of returning from an initializer is counter-intuitive both syntactically and semantically.

The actual *behavior* of `return nil` is very sensible, so the behavior, I imagine `self = nil`, would largely mean the same (except not needed to return immediately and allowing non-self-accessing code to be executed before return). Being able to assign `nil` to a non-optional (ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to initialize self to nil? That is what `self = nil` means if `self` is of type `inout Self`. If `self` is of type `inout Self` and Self is not ExpressibleByNilLiteral, then it must be an error to assign nil to self. Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to initialize an object in-place and doesn't look like it should return anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init` syntax could completely flip this logic, but making the initializer essentially a static function that returns an object. In this case the initializer could be made to specify the return type (that is the supertype of all possible factory-created objects) and assigning to self would be forbidden because there is not self yet:

extension MyProtocol {

public factory init(weCool: Bool) -> MyProtocol {
self = MyImpl() // error: cannot assign to `self` in a factory initializer
self.init(...) // error: cannot make a delegating initializer call in a factory initializer
if weCool {
return MyCoolImpl()
} else {
return MyUncoolImpl()
}
}

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2 (as in `self.member = value`), which could be extended in a non-factory initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while giving a more reliable performance guarantee that this member will not be copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

If `self` is not of type `inout Self?`, then what is the type of `self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms to `ExpressibleByNilLiteral`, in which case you are able to assign `self = nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped optionals are no longer their own type, I’m not sure that’s possible. But even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self` would have to be of type `inout Self?`–which is intriguing but potentially more boilerplatey than the status quo.
On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org> wrote:
Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and since `self` can only be initialized once, this would mean that after `self = nil`, you won't be allowed to access `self` in your initializer at all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to treat `self` as `inout Self?`, because the only place it can be `nil` is the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable initializers (essentially making `self` look like `inout Self?` instead of `inout Self` with magical `return nil`), so that all initializers uniformly can be written in `self = ...` form for clarity and convenience purposes. This should, theoretically, be nothing but a `defer { return nil }` type of rewrite, so I don't see any major difficulties implementing this. This is especially useful for failable-initializing enums where the main switch simply assigns to self in all cases and the rest of the initializer does some post-processing.

I don't see how to avoid source incompatibility and uglification of failable initializer implementations here. Allowing `self = nil` inside a failable initializer would require `self` to be an optional. That in turn would require every use of `self` in the initializer to be nil-checked or forced. I don't think that loss everywhere outweighs the gain of `self = nil` in some places.

--
Greg Parker gparker@apple.com Runtime Wrangler

_______________________________________________
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

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

IIRC I had a discussion with Douglas Gregor about the overriding aspect of factory initializers, and the takeaway was that it would just be like convenience initializers. Technically, convenience initializers cannot be overridden, but a subclass *can* implement a convenience method with the same signature as its superclass' convenience method. The only difference is it can't call the super initializer. I think this *does* make the most sense, because I'm not sure super.init for an indirect initializer makes much sense, and if you really wanted to do that, you could just call the initializer directly (aka "let superReturnValue = Type()). But happy to change if you feel strongly it should be allowed!

I left out the Objective-C/C interoperability aspects because IMO they aren't necessary for this proposal. This proposal is specifically limited to adding a new indirect initializer to Swift. I could mention that it would be exposed to Objective-C just like other initializers, but anything more than that I think should be a separate proposal (such as how C/Objective-C initializers would be imported).

Also, what parts sound like a personal letter? The motivation + examples are motivated by personal experience, and so I wrote them from my perspective (similar to other proposals), but the proposed solution + detailed design should be straightforward and void of opinions.

···

On Jun 10, 2017, at 5:25 PM, Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

Looks good, but I have a few thoughts on it:

* I think indirect initializers *shoud* be overridable, but only by other indirect initializers. This will allow subclasses of the factory to expand the factory method by adding new possible instances to return.
* You did not include the specification of implementation details that I provided as well as C/Objective-C interoperability changes.
* The proposal is formulated more like a personal opinion, rather then a formal specification. It sounds like a personal letter. I'd recommend writing it similarly as you'd write a wikipedia page.

On Jun 11, 2017, at 1:12 AM, Riley Testut <rileytestut@gmail.com> wrote:

Awesome! Updated my proposal to include what I believed to be the relevant portions of your indirect initializer idea. Let me know if there’s anything I missed or should change :-)

https://github.com/rileytestut/swift-evolution/blob/master/proposals/NNNN-factory-initializers.md

On Jun 10, 2017, at 12:43 PM, Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

Hi, Riley!

I think that's a great idea! We can merge the second part of my proposal (the `indirect init`) into your one and refine and consolidate the prerequisite proposal (about returning from `init` and possibly in-place member initializers) and bunch them up into a proposal cluster (the way swift coders did).
Feel free to tear out any chunks from my proposal, while I think about a more in-depth rationale about revamping initialization syntax. :slightly_smiling_face:

On Jun 10, 2017, at 8:36 PM, Riley Testut <rileytestut@gmail.com> wrote:

Hi Gor :wave:

I’m very much in fan of a unified initialization syntax. I submitted my own proposal for factory initializers a while back, but since it wasn’t a focus of Swift 3 or 4 I haven’t followed up on it recently. In the time since last working on it, I came to my own conclusion that rather than focusing on factory initialization, the overall initialization process should be simplified, which I’m glad to see someone else has realized as well :-)

Here’s my proposal for reference: Proposal: Factory Initializers by rileytestut · Pull Request #247 · apple/swift-evolution · GitHub Originally I used the “factory” keyword, but I think your “indirect” keyword may be a better fit (since it has precedent in the language and is not limited to “just” being about factory initialization). To divide your proposal up into smaller pieces for review, maybe we could update my proposal to use your indirect keyword, and then start a separate topic/proposal for the remaining aspects of your proposal? I agree that splitting it into smaller chunks may be better for the process.

Let me know what you think!

Riley

On Jun 10, 2017, at 3:33 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org> wrote:

This is a very interesting read.

Thanks you! I tried to make it as clear and detailed as possible. :slightly_smiling_face:

We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

I was writing the proposal and was just about to write `factory init`, when it occurred to me: enums already have a keyword that does something very similar. It seemed to me that an initializer that doesn't initialize the instance in-place, but returns a completely separate instance from somewhere else, is kinda "indirectly" initializing the instance. Plus, the already established keyword and its semantic would reduce the learning curve for this new feature and separate it from a single specific use case (the "factory method" pattern).

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

I think the `return` can be easily implemented first, while opening up an opportunity to later implement `indirect init`. The reason why I unified them was that the `return` idea on its own has very limited merit and could the thought of as a low-priority cosmetic enhancement. I wouldn't want it to be viewed that way because the primary purpose of that idea is to enable `indirect init` (which Cocoa and Cocoa Touch developers would be very happy about).

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

Very good point. The challenge is to correctly separate them, without losing context in their respective proposals and without bleeding the proposals into each other.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

I'd never send a pull request to swift-evolution without thoroughly discussing it here. I just though, if I'm going to write a whole proposal with examples and motivation, it would be easier to demonstrate it and discuss in with the community If I just went ahead and wrote the whole thing and sent the link. This way it would be clearer to the reader and the discussed changes would be accurately reflected by the commits I'd make to my proposal.

Original Message

On Jun 10, 2017, at 2:38 AM, Daryle Walker via swift-evolution <swift-evolution@swift.org> wrote:

On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <gor@gyolchanyan.com> wrote:
Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/master/proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed it wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

This is a very interesting read. We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Cool. I have reservations about idea #3, but we can tackle that another day. (Real life things beckon.) But suffice it to say that I now really, really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self` non-optional.
This would make `return nil` less out-of-place, like you said, while still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax, while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it to change the signature as well as remove any compiler assumptions about the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:
So far, we've discussed two ways of interpreting `self = nil`, both of which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as counter-intuitive, but recall that `return nil` is just as much of a special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax because the initializer notionally has no return value. Personally, I have always disliked `return nil` in failable initializers for that reason, but I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because, in the case of a failable initializer, `return nil` continues to have the same meaning if we consider the return value of the initializer to be of type `Self?`. For that reason, I think your idea #2 is quite clever, and it would go a long way in making `return nil` a lot less odd. It also increases the expressivity of initializers because it allows one to set the value of self and also return in one statement, clearly demonstrating the intention that no other code in the initializer should be run before returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with initialization semantics, it provides more uniform syntax and it's a bit less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more cumbersome. Implicitly unwrapped optionals are a bit difficult, but this "variation" of it is much more restrictive then the normal ones, because unlike normal implicitly unwrapped optionals, this one cannot be accessed after being assigned nil (and it also cannot be indirectly assigned `nil`, because escaping `self` is not allowed before full initialization), so there is only one possible place it can be set to nil and that's directly in the initializer. This means that `self` can be safely treated as `inout Self` before being set to nil (and after being set to nil, it doesn't matter any more because you aren't allowed to access it, due to not being fully initialized).

I have to say, I don’t like either of these explanations at all. I think having a “special” IUO is a difficult sell; it is just conceptually too complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language wonkier because it currently has a parallel wonky feature in `return nil` seems like the wrong way to go. In addition, there’s nothing gained here that cannot be done with a defer statement; of course, defer statements might not be very elegant, but it would certainly be less wonky than inventing a new variation on an IUO to allow assignment of nil to self... For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic and the restrictions of `self as inout Self!` are imposed by already existing and well-understood initialization logic, so the provided guarantees don't really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:
I think a good approach would be to have `self = nil` only mean `the initializer is going to fail` because if your type is ExpressibleByNilLiteral, it means that the `nil` of your type already carries the same meaning as if your type was not ExpressibleByNilLiteral and was an optional instead, so having a failable initializer doesn't really make sense in that case (since you could've initialized `self` to its own `nil` in case of failure). Still, some valid use cases may exist, so the natural (and quite intuitive) way to circumvent this would be to call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different thing in an initializer than it does in a function? Essentially, then, you’re creating your own variation on an implicitly unwrapped optional, where `self` is of type `inout Self?` for assignment in initializers only but not for any other purpose. Implicitly unwrapped optionals are hard to reason about, and having a variation on it would be even harder to understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however, I do think Greg is right that it would create more boilerplate than the current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:
The type of `self` could remain `inout Self` inside the failable initializer. The ability to assign nil would be a compiler magic (much like `return nil` is compiler magic) that is meant to introduce uniformity to the initialization logic.

The idea is to define all different ways initialization can take place and expand them to be used uniformly on both `self` and all its members, as well as remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
  1. delegating initializer
  2. assigning to self
  3. returning nil

#1: The delegating initializer is pretty much perfect at this point, in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside failable initializers.

#3: The only thing that can be returned from an initializer is `nil`, which is compiler magic, so we can thing of it as a misnomer (because we aren't really **returning** anything).

If, for a second, we forget about potential factory initializers, returning anything from an initializer doesn't make much sense, because an initializer is conceptually meant to bring an existing object in memory to a type-specific valid state. This semantic was very explicitly in Objective-C with `[[MyType alloc] init]`. Especially since even syntactically, the initializer does not specify any return type, the idea of returning from an initializer is counter-intuitive both syntactically and semantically.

The actual *behavior* of `return nil` is very sensible, so the behavior, I imagine `self = nil`, would largely mean the same (except not needed to return immediately and allowing non-self-accessing code to be executed before return). Being able to assign `nil` to a non-optional (ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to initialize self to nil? That is what `self = nil` means if `self` is of type `inout Self`. If `self` is of type `inout Self` and Self is not ExpressibleByNilLiteral, then it must be an error to assign nil to self. Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to initialize an object in-place and doesn't look like it should return anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init` syntax could completely flip this logic, but making the initializer essentially a static function that returns an object. In this case the initializer could be made to specify the return type (that is the supertype of all possible factory-created objects) and assigning to self would be forbidden because there is not self yet:

extension MyProtocol {

  public factory init(weCool: Bool) -> MyProtocol {
    self = MyImpl() // error: cannot assign to `self` in a factory initializer
    self.init(...) // error: cannot make a delegating initializer call in a factory initializer
    if weCool {
      return MyCoolImpl()
    } else {
      return MyUncoolImpl()
    }
  }

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2 (as in `self.member = value`), which could be extended in a non-factory initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while giving a more reliable performance guarantee that this member will not be copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

If `self` is not of type `inout Self?`, then what is the type of `self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms to `ExpressibleByNilLiteral`, in which case you are able to assign `self = nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped optionals are no longer their own type, I’m not sure that’s possible. But even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self` would have to be of type `inout Self?`–which is intriguing but potentially more boilerplatey than the status quo.

On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org> wrote:
Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and since `self` can only be initialized once, this would mean that after `self = nil`, you won't be allowed to access `self` in your initializer at all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to treat `self` as `inout Self?`, because the only place it can be `nil` is the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable initializers (essentially making `self` look like `inout Self?` instead of `inout Self` with magical `return nil`), so that all initializers uniformly can be written in `self = ...` form for clarity and convenience purposes. This should, theoretically, be nothing but a `defer { return nil }` type of rewrite, so I don't see any major difficulties implementing this. This is especially useful for failable-initializing enums where the main switch simply assigns to self in all cases and the rest of the initializer does some post-processing.

I don't see how to avoid source incompatibility and uglification of failable initializer implementations here. Allowing `self = nil` inside a failable initializer would require `self` to be an optional. That in turn would require every use of `self` in the initializer to be nil-checked or forced. I don't think that loss everywhere outweighs the gain of `self = nil` in some places.

--
Greg Parker gparker@apple.com Runtime Wrangler

_______________________________________________
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

The difference between a convenience initializer and an indirect initializer is that convenience initializer has to initialize an existing instance, so its options of delegating the responsibility are limited by the guarantees that the initializer requires. On the other hand, an indirect initializer is pretty much a normal static function which doesn't need any guarantees at all, so it could get the instance from wherever it wanted. I can't say I'm totally sure about this, but it seems like limiting the overridability wouldn't server any real purpose.

I initially decided to include the Objective-C/C part because the current behavior of imported initializers exactly matches that of an indirect initializer, so if these changes would be made, *all* non-indirect initializers (both native and imported) would have static typing guarantees that could be exploited by the compiler. I don't think it's critical, because Swift is now at the brink of major version 4 and this odd imported initializer behavior hasn't seemed to have caused any trouble. Still, I think as a sneak peek at a future proposal to clean up the imported initializers would be warranted as a side-note in this proposal for the core team to get a better understanding of where this could go.

About the formulation: I'm just being overly pedantic about everything as usual. I just thought that the core team would prefer something more like a spec document, rather then a favor. It's really the least important aspect at this point, so it's fine :slightly_smiling_face:

···

On Jun 11, 2017, at 1:54 AM, Riley Testut <rileytestut@gmail.com> wrote:

IIRC I had a discussion with Douglas Gregor about the overriding aspect of factory initializers, and the takeaway was that it would just be like convenience initializers. Technically, convenience initializers cannot be overridden, but a subclass *can* implement a convenience method with the same signature as its superclass' convenience method. The only difference is it can't call the super initializer. I think this *does* make the most sense, because I'm not sure super.init for an indirect initializer makes much sense, and if you really wanted to do that, you could just call the initializer directly (aka "let superReturnValue = Type()). But happy to change if you feel strongly it should be allowed!

I left out the Objective-C/C interoperability aspects because IMO they aren't necessary for this proposal. This proposal is specifically limited to adding a new indirect initializer to Swift. I could mention that it would be exposed to Objective-C just like other initializers, but anything more than that I think should be a separate proposal (such as how C/Objective-C initializers would be imported).

Also, what parts sound like a personal letter? The motivation + examples are motivated by personal experience, and so I wrote them from my perspective (similar to other proposals), but the proposed solution + detailed design should be straightforward and void of opinions.

On Jun 10, 2017, at 5:25 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:

Looks good, but I have a few thoughts on it:

* I think indirect initializers *shoud* be overridable, but only by other indirect initializers. This will allow subclasses of the factory to expand the factory method by adding new possible instances to return.
* You did not include the specification of implementation details that I provided as well as C/Objective-C interoperability changes.
* The proposal is formulated more like a personal opinion, rather then a formal specification. It sounds like a personal letter. I'd recommend writing it similarly as you'd write a wikipedia page.

On Jun 11, 2017, at 1:12 AM, Riley Testut <rileytestut@gmail.com <mailto:rileytestut@gmail.com>> wrote:

Awesome! Updated my proposal to include what I believed to be the relevant portions of your indirect initializer idea. Let me know if there’s anything I missed or should change :-)

https://github.com/rileytestut/swift-evolution/blob/master/proposals/NNNN-factory-initializers.md

On Jun 10, 2017, at 12:43 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:

Hi, Riley!

I think that's a great idea! We can merge the second part of my proposal (the `indirect init`) into your one and refine and consolidate the prerequisite proposal (about returning from `init` and possibly in-place member initializers) and bunch them up into a proposal cluster (the way swift coders did).
Feel free to tear out any chunks from my proposal, while I think about a more in-depth rationale about revamping initialization syntax. :slightly_smiling_face:

On Jun 10, 2017, at 8:36 PM, Riley Testut <rileytestut@gmail.com <mailto:rileytestut@gmail.com>> wrote:

Hi Gor :wave:

I’m very much in fan of a unified initialization syntax. I submitted my own proposal for factory initializers a while back, but since it wasn’t a focus of Swift 3 or 4 I haven’t followed up on it recently. In the time since last working on it, I came to my own conclusion that rather than focusing on factory initialization, the overall initialization process should be simplified, which I’m glad to see someone else has realized as well :-)

Here’s my proposal for reference: Proposal: Factory Initializers by rileytestut · Pull Request #247 · apple/swift-evolution · GitHub Originally I used the “factory” keyword, but I think your “indirect” keyword may be a better fit (since it has precedent in the language and is not limited to “just” being about factory initialization). To divide your proposal up into smaller pieces for review, maybe we could update my proposal to use your indirect keyword, and then start a separate topic/proposal for the remaining aspects of your proposal? I agree that splitting it into smaller chunks may be better for the process.

Let me know what you think!

Riley

On Jun 10, 2017, at 3:33 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This is a very interesting read.

Thanks you! I tried to make it as clear and detailed as possible. :slightly_smiling_face:

We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

I was writing the proposal and was just about to write `factory init`, when it occurred to me: enums already have a keyword that does something very similar. It seemed to me that an initializer that doesn't initialize the instance in-place, but returns a completely separate instance from somewhere else, is kinda "indirectly" initializing the instance. Plus, the already established keyword and its semantic would reduce the learning curve for this new feature and separate it from a single specific use case (the "factory method" pattern).

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

I think the `return` can be easily implemented first, while opening up an opportunity to later implement `indirect init`. The reason why I unified them was that the `return` idea on its own has very limited merit and could the thought of as a low-priority cosmetic enhancement. I wouldn't want it to be viewed that way because the primary purpose of that idea is to enable `indirect init` (which Cocoa and Cocoa Touch developers would be very happy about).

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

Very good point. The challenge is to correctly separate them, without losing context in their respective proposals and without bleeding the proposals into each other.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

I'd never send a pull request to swift-evolution without thoroughly discussing it here. I just though, if I'm going to write a whole proposal with examples and motivation, it would be easier to demonstrate it and discuss in with the community If I just went ahead and wrote the whole thing and sent the link. This way it would be clearer to the reader and the discussed changes would be accurately reflected by the commits I'd make to my proposal.

Original Message

On Jun 10, 2017, at 2:38 AM, Daryle Walker via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/master/proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed it wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

This is a very interesting read. We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Cool. I have reservations about idea #3, but we can tackle that another day. (Real life things beckon.) But suffice it to say that I now really, really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self` non-optional.
This would make `return nil` less out-of-place, like you said, while still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax, while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it to change the signature as well as remove any compiler assumptions about the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
So far, we've discussed two ways of interpreting `self = nil`, both of which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as counter-intuitive, but recall that `return nil` is just as much of a special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax because the initializer notionally has no return value. Personally, I have always disliked `return nil` in failable initializers for that reason, but I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because, in the case of a failable initializer, `return nil` continues to have the same meaning if we consider the return value of the initializer to be of type `Self?`. For that reason, I think your idea #2 is quite clever, and it would go a long way in making `return nil` a lot less odd. It also increases the expressivity of initializers because it allows one to set the value of self and also return in one statement, clearly demonstrating the intention that no other code in the initializer should be run before returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with initialization semantics, it provides more uniform syntax and it's a bit less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more cumbersome. Implicitly unwrapped optionals are a bit difficult, but this "variation" of it is much more restrictive then the normal ones, because unlike normal implicitly unwrapped optionals, this one cannot be accessed after being assigned nil (and it also cannot be indirectly assigned `nil`, because escaping `self` is not allowed before full initialization), so there is only one possible place it can be set to nil and that's directly in the initializer. This means that `self` can be safely treated as `inout Self` before being set to nil (and after being set to nil, it doesn't matter any more because you aren't allowed to access it, due to not being fully initialized).

I have to say, I don’t like either of these explanations at all. I think having a “special” IUO is a difficult sell; it is just conceptually too complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language wonkier because it currently has a parallel wonky feature in `return nil` seems like the wrong way to go. In addition, there’s nothing gained here that cannot be done with a defer statement; of course, defer statements might not be very elegant, but it would certainly be less wonky than inventing a new variation on an IUO to allow assignment of nil to self... For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic and the restrictions of `self as inout Self!` are imposed by already existing and well-understood initialization logic, so the provided guarantees don't really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
I think a good approach would be to have `self = nil` only mean `the initializer is going to fail` because if your type is ExpressibleByNilLiteral, it means that the `nil` of your type already carries the same meaning as if your type was not ExpressibleByNilLiteral and was an optional instead, so having a failable initializer doesn't really make sense in that case (since you could've initialized `self` to its own `nil` in case of failure). Still, some valid use cases may exist, so the natural (and quite intuitive) way to circumvent this would be to call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different thing in an initializer than it does in a function? Essentially, then, you’re creating your own variation on an implicitly unwrapped optional, where `self` is of type `inout Self?` for assignment in initializers only but not for any other purpose. Implicitly unwrapped optionals are hard to reason about, and having a variation on it would be even harder to understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however, I do think Greg is right that it would create more boilerplate than the current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
The type of `self` could remain `inout Self` inside the failable initializer. The ability to assign nil would be a compiler magic (much like `return nil` is compiler magic) that is meant to introduce uniformity to the initialization logic.

The idea is to define all different ways initialization can take place and expand them to be used uniformly on both `self` and all its members, as well as remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
  1. delegating initializer
  2. assigning to self
  3. returning nil

#1: The delegating initializer is pretty much perfect at this point, in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside failable initializers.

#3: The only thing that can be returned from an initializer is `nil`, which is compiler magic, so we can thing of it as a misnomer (because we aren't really **returning** anything).

If, for a second, we forget about potential factory initializers, returning anything from an initializer doesn't make much sense, because an initializer is conceptually meant to bring an existing object in memory to a type-specific valid state. This semantic was very explicitly in Objective-C with `[[MyType alloc] init]`. Especially since even syntactically, the initializer does not specify any return type, the idea of returning from an initializer is counter-intuitive both syntactically and semantically.

The actual *behavior* of `return nil` is very sensible, so the behavior, I imagine `self = nil`, would largely mean the same (except not needed to return immediately and allowing non-self-accessing code to be executed before return). Being able to assign `nil` to a non-optional (ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to initialize self to nil? That is what `self = nil` means if `self` is of type `inout Self`. If `self` is of type `inout Self` and Self is not ExpressibleByNilLiteral, then it must be an error to assign nil to self. Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to initialize an object in-place and doesn't look like it should return anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init` syntax could completely flip this logic, but making the initializer essentially a static function that returns an object. In this case the initializer could be made to specify the return type (that is the supertype of all possible factory-created objects) and assigning to self would be forbidden because there is not self yet:

extension MyProtocol {

  public factory init(weCool: Bool) -> MyProtocol {
    self = MyImpl() // error: cannot assign to `self` in a factory initializer
    self.init(...) // error: cannot make a delegating initializer call in a factory initializer
    if weCool {
      return MyCoolImpl()
    } else {
      return MyUncoolImpl()
    }
  }

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2 (as in `self.member = value`), which could be extended in a non-factory initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while giving a more reliable performance guarantee that this member will not be copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

If `self` is not of type `inout Self?`, then what is the type of `self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms to `ExpressibleByNilLiteral`, in which case you are able to assign `self = nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped optionals are no longer their own type, I’m not sure that’s possible. But even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self` would have to be of type `inout Self?`–which is intriguing but potentially more boilerplatey than the status quo.
On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and since `self` can only be initialized once, this would mean that after `self = nil`, you won't be allowed to access `self` in your initializer at all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to treat `self` as `inout Self?`, because the only place it can be `nil` is the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com <mailto:gparker@apple.com>> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable initializers (essentially making `self` look like `inout Self?` instead of `inout Self` with magical `return nil`), so that all initializers uniformly can be written in `self = ...` form for clarity and convenience purposes. This should, theoretically, be nothing but a `defer { return nil }` type of rewrite, so I don't see any major difficulties implementing this. This is especially useful for failable-initializing enums where the main switch simply assigns to self in all cases and the rest of the initializer does some post-processing.

I don't see how to avoid source incompatibility and uglification of failable initializer implementations here. Allowing `self = nil` inside a failable initializer would require `self` to be an optional. That in turn would require every use of `self` in the initializer to be nil-checked or forced. I don't think that loss everywhere outweighs the gain of `self = nil` in some places.

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler

_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

I always wondered, why is `indirect` allowed on the `enum` itself? Wouldn't it make more sense to apply it to individual cases that recursively refer to the `enum`?
This question also applies to access modifiers on extensions. So, what is it supposed to do? Change the default access modifier from `internal` to whatever I specify? That's just confusing, reduces readability and the syntactic gain is marginal at best.
If the `indirect` confusion becomes real, I'd suggest getting rid of `indirect enum` and using `indirect case` instead.

···

On Jun 11, 2017, at 11:05 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org> wrote:

The proposal is looking good to me. :) It will also enable easy support for custom views using XIBs in iOS development without unnecessary view nesting.

For instance the function from this example ios - Loading a XIB file to a UIView Swift - Stack Overflow could be used directly inside an init:

class MyView : UIView {
     
      indirect init() {
            return MyView.instantiateFromXib()
            // Or after SR-0068
            return Self.instantiateFromXib()
      }
}
There is still one little thing that bothers me, it might be a little bit confusing to have two different meanings of indirect on enums.

indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)
     
    // This might makes no sense, but it would still be possible after
    // this proposal.
    indirect init(other: ArithmeticExpression) {
       return other
    }
     
    // Furthermore if the keyboard is applied to the enum
    // directly all other `indirect` uses are inferred.
    // Will this be implicitly `indirect` because of the previous fact?
    init() { … }
}

--
Adrian Zubarev
Sent with Airmail

Am 11. Juni 2017 um 00:38:56, Riley Testut via swift-evolution (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) schrieb:

Awesome! Updated my proposal to include what I believed to be the relevant portions of your indirect initializer idea. Let me know if there’s anything I missed or should change :-)

https://github.com/rileytestut/swift-evolution/blob/master/proposals/NNNN-factory-initializers.md

On Jun 10, 2017, at 12:43 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:

Hi, Riley!

I think that's a great idea! We can merge the second part of my proposal (the `indirect init`) into your one and refine and consolidate the prerequisite proposal (about returning from `init` and possibly in-place member initializers) and bunch them up into a proposal cluster (the way swift coders did).
Feel free to tear out any chunks from my proposal, while I think about a more in-depth rationale about revamping initialization syntax. :slightly_smiling_face:

On Jun 10, 2017, at 8:36 PM, Riley Testut <rileytestut@gmail.com <mailto:rileytestut@gmail.com>> wrote:

Hi Gor :wave:

I’m very much in fan of a unified initialization syntax. I submitted my own proposal for factory initializers a while back, but since it wasn’t a focus of Swift 3 or 4 I haven’t followed up on it recently. In the time since last working on it, I came to my own conclusion that rather than focusing on factory initialization, the overall initialization process should be simplified, which I’m glad to see someone else has realized as well :-)

Here’s my proposal for reference: Proposal: Factory Initializers by rileytestut · Pull Request #247 · apple/swift-evolution · GitHub Originally I used the “factory” keyword, but I think your “indirect” keyword may be a better fit (since it has precedent in the language and is not limited to “just” being about factory initialization). To divide your proposal up into smaller pieces for review, maybe we could update my proposal to use your indirect keyword, and then start a separate topic/proposal for the remaining aspects of your proposal? I agree that splitting it into smaller chunks may be better for the process.

Let me know what you think!

Riley

On Jun 10, 2017, at 3:33 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This is a very interesting read.

Thanks you! I tried to make it as clear and detailed as possible. :slightly_smiling_face:

We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

I was writing the proposal and was just about to write `factory init`, when it occurred to me: enums already have a keyword that does something very similar. It seemed to me that an initializer that doesn't initialize the instance in-place, but returns a completely separate instance from somewhere else, is kinda "indirectly" initializing the instance. Plus, the already established keyword and its semantic would reduce the learning curve for this new feature and separate it from a single specific use case (the "factory method" pattern).

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

I think the `return` can be easily implemented first, while opening up an opportunity to later implement `indirect init`. The reason why I unified them was that the `return` idea on its own has very limited merit and could the thought of as a low-priority cosmetic enhancement. I wouldn't want it to be viewed that way because the primary purpose of that idea is to enable `indirect init` (which Cocoa and Cocoa Touch developers would be very happy about).

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

Very good point. The challenge is to correctly separate them, without losing context in their respective proposals and without bleeding the proposals into each other.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

I'd never send a pull request to swift-evolution without thoroughly discussing it here. I just though, if I'm going to write a whole proposal with examples and motivation, it would be easier to demonstrate it and discuss in with the community If I just went ahead and wrote the whole thing and sent the link. This way it would be clearer to the reader and the discussed changes would be accurately reflected by the commits I'd make to my proposal.

Original Message

On Jun 10, 2017, at 2:38 AM, Daryle Walker via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/master/proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed it wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

This is a very interesting read. We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Cool. I have reservations about idea #3, but we can tackle that another day. (Real life things beckon.) But suffice it to say that I now really, really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self` non-optional.
This would make `return nil` less out-of-place, like you said, while still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax, while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it to change the signature as well as remove any compiler assumptions about the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
So far, we've discussed two ways of interpreting `self = nil`, both of which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as counter-intuitive, but recall that `return nil` is just as much of a special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax because the initializer notionally has no return value. Personally, I have always disliked `return nil` in failable initializers for that reason, but I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because, in the case of a failable initializer, `return nil` continues to have the same meaning if we consider the return value of the initializer to be of type `Self?`. For that reason, I think your idea #2 is quite clever, and it would go a long way in making `return nil` a lot less odd. It also increases the expressivity of initializers because it allows one to set the value of self and also return in one statement, clearly demonstrating the intention that no other code in the initializer should be run before returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with initialization semantics, it provides more uniform syntax and it's a bit less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more cumbersome. Implicitly unwrapped optionals are a bit difficult, but this "variation" of it is much more restrictive then the normal ones, because unlike normal implicitly unwrapped optionals, this one cannot be accessed after being assigned nil (and it also cannot be indirectly assigned `nil`, because escaping `self` is not allowed before full initialization), so there is only one possible place it can be set to nil and that's directly in the initializer. This means that `self` can be safely treated as `inout Self` before being set to nil (and after being set to nil, it doesn't matter any more because you aren't allowed to access it, due to not being fully initialized).

I have to say, I don’t like either of these explanations at all. I think having a “special” IUO is a difficult sell; it is just conceptually too complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language wonkier because it currently has a parallel wonky feature in `return nil` seems like the wrong way to go. In addition, there’s nothing gained here that cannot be done with a defer statement; of course, defer statements might not be very elegant, but it would certainly be less wonky than inventing a new variation on an IUO to allow assignment of nil to self... For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic and the restrictions of `self as inout Self!` are imposed by already existing and well-understood initialization logic, so the provided guarantees don't really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
I think a good approach would be to have `self = nil` only mean `the initializer is going to fail` because if your type is ExpressibleByNilLiteral, it means that the `nil` of your type already carries the same meaning as if your type was not ExpressibleByNilLiteral and was an optional instead, so having a failable initializer doesn't really make sense in that case (since you could've initialized `self` to its own `nil` in case of failure). Still, some valid use cases may exist, so the natural (and quite intuitive) way to circumvent this would be to call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different thing in an initializer than it does in a function? Essentially, then, you’re creating your own variation on an implicitly unwrapped optional, where `self` is of type `inout Self?` for assignment in initializers only but not for any other purpose. Implicitly unwrapped optionals are hard to reason about, and having a variation on it would be even harder to understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however, I do think Greg is right that it would create more boilerplate than the current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
The type of `self` could remain `inout Self` inside the failable initializer. The ability to assign nil would be a compiler magic (much like `return nil` is compiler magic) that is meant to introduce uniformity to the initialization logic.

The idea is to define all different ways initialization can take place and expand them to be used uniformly on both `self` and all its members, as well as remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
1. delegating initializer
2. assigning to self
3. returning nil

#1: The delegating initializer is pretty much perfect at this point, in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside failable initializers.

#3: The only thing that can be returned from an initializer is `nil`, which is compiler magic, so we can thing of it as a misnomer (because we aren't really **returning** anything).

If, for a second, we forget about potential factory initializers, returning anything from an initializer doesn't make much sense, because an initializer is conceptually meant to bring an existing object in memory to a type-specific valid state. This semantic was very explicitly in Objective-C with `[[MyType alloc] init]`. Especially since even syntactically, the initializer does not specify any return type, the idea of returning from an initializer is counter-intuitive both syntactically and semantically.

The actual *behavior* of `return nil` is very sensible, so the behavior, I imagine `self = nil`, would largely mean the same (except not needed to return immediately and allowing non-self-accessing code to be executed before return). Being able to assign `nil` to a non-optional (ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to initialize self to nil? That is what `self = nil` means if `self` is of type `inout Self`. If `self` is of type `inout Self` and Self is not ExpressibleByNilLiteral, then it must be an error to assign nil to self. Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to initialize an object in-place and doesn't look like it should return anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init` syntax could completely flip this logic, but making the initializer essentially a static function that returns an object. In this case the initializer could be made to specify the return type (that is the supertype of all possible factory-created objects) and assigning to self would be forbidden because there is not self yet:

extension MyProtocol {

public factory init(weCool: Bool) -> MyProtocol {
self = MyImpl() // error: cannot assign to `self` in a factory initializer
self.init(...) // error: cannot make a delegating initializer call in a factory initializer
if weCool {
return MyCoolImpl()
} else {
return MyUncoolImpl()
}
}

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2 (as in `self.member = value`), which could be extended in a non-factory initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while giving a more reliable performance guarantee that this member will not be copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

If `self` is not of type `inout Self?`, then what is the type of `self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms to `ExpressibleByNilLiteral`, in which case you are able to assign `self = nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped optionals are no longer their own type, I’m not sure that’s possible. But even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self` would have to be of type `inout Self?`–which is intriguing but potentially more boilerplatey than the status quo.
On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and since `self` can only be initialized once, this would mean that after `self = nil`, you won't be allowed to access `self` in your initializer at all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to treat `self` as `inout Self?`, because the only place it can be `nil` is the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com <mailto:gparker@apple.com>> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable initializers (essentially making `self` look like `inout Self?` instead of `inout Self` with magical `return nil`), so that all initializers uniformly can be written in `self = ...` form for clarity and convenience purposes. This should, theoretically, be nothing but a `defer { return nil }` type of rewrite, so I don't see any major difficulties implementing this. This is especially useful for failable-initializing enums where the main switch simply assigns to self in all cases and the rest of the initializer does some post-processing.

I don't see how to avoid source incompatibility and uglification of failable initializer implementations here. Allowing `self = nil` inside a failable initializer would require `self` to be an optional. That in turn would require every use of `self` in the initializer to be nil-checked or forced. I don't think that loss everywhere outweighs the gain of `self = nil` in some places.

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler

_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

I prefer ‘factory’ myself.

Charles

···

On Jun 11, 2017, at 4:04 AM, Michael Grewal via swift-evolution <swift-evolution@swift.org> wrote:

Hey how about a new company called
Kernal*saun*$eeders*=ultimatetruecode.ORG <http://ultimatetruecode.org/&gt;
I have the I dream of the kings of live script support
No one can top us

Sent from my iPhone

On Jun 10, 2017, at 3:12 PM, Riley Testut via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Awesome! Updated my proposal to include what I believed to be the relevant portions of your indirect initializer idea. Let me know if there’s anything I missed or should change :-)

https://github.com/rileytestut/swift-evolution/blob/master/proposals/NNNN-factory-initializers.md

On Jun 10, 2017, at 12:43 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:

Hi, Riley!

I think that's a great idea! We can merge the second part of my proposal (the `indirect init`) into your one and refine and consolidate the prerequisite proposal (about returning from `init` and possibly in-place member initializers) and bunch them up into a proposal cluster (the way swift coders did).
Feel free to tear out any chunks from my proposal, while I think about a more in-depth rationale about revamping initialization syntax. :slightly_smiling_face:

On Jun 10, 2017, at 8:36 PM, Riley Testut <rileytestut@gmail.com <mailto:rileytestut@gmail.com>> wrote:

Hi Gor :wave:

I’m very much in fan of a unified initialization syntax. I submitted my own proposal for factory initializers a while back, but since it wasn’t a focus of Swift 3 or 4 I haven’t followed up on it recently. In the time since last working on it, I came to my own conclusion that rather than focusing on factory initialization, the overall initialization process should be simplified, which I’m glad to see someone else has realized as well :-)

Here’s my proposal for reference: Proposal: Factory Initializers by rileytestut · Pull Request #247 · apple/swift-evolution · GitHub Originally I used the “factory” keyword, but I think your “indirect” keyword may be a better fit (since it has precedent in the language and is not limited to “just” being about factory initialization). To divide your proposal up into smaller pieces for review, maybe we could update my proposal to use your indirect keyword, and then start a separate topic/proposal for the remaining aspects of your proposal? I agree that splitting it into smaller chunks may be better for the process.

Let me know what you think!

Riley

On Jun 10, 2017, at 3:33 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This is a very interesting read.

Thanks you! I tried to make it as clear and detailed as possible. :slightly_smiling_face:

We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

I was writing the proposal and was just about to write `factory init`, when it occurred to me: enums already have a keyword that does something very similar. It seemed to me that an initializer that doesn't initialize the instance in-place, but returns a completely separate instance from somewhere else, is kinda "indirectly" initializing the instance. Plus, the already established keyword and its semantic would reduce the learning curve for this new feature and separate it from a single specific use case (the "factory method" pattern).

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

I think the `return` can be easily implemented first, while opening up an opportunity to later implement `indirect init`. The reason why I unified them was that the `return` idea on its own has very limited merit and could the thought of as a low-priority cosmetic enhancement. I wouldn't want it to be viewed that way because the primary purpose of that idea is to enable `indirect init` (which Cocoa and Cocoa Touch developers would be very happy about).

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

Very good point. The challenge is to correctly separate them, without losing context in their respective proposals and without bleeding the proposals into each other.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

I'd never send a pull request to swift-evolution without thoroughly discussing it here. I just though, if I'm going to write a whole proposal with examples and motivation, it would be easier to demonstrate it and discuss in with the community If I just went ahead and wrote the whole thing and sent the link. This way it would be clearer to the reader and the discussed changes would be accurately reflected by the commits I'd make to my proposal.

Original Message

On Jun 10, 2017, at 2:38 AM, Daryle Walker via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/master/proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed it wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

This is a very interesting read. We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Cool. I have reservations about idea #3, but we can tackle that another day. (Real life things beckon.) But suffice it to say that I now really, really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self` non-optional.
This would make `return nil` less out-of-place, like you said, while still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax, while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it to change the signature as well as remove any compiler assumptions about the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
So far, we've discussed two ways of interpreting `self = nil`, both of which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as counter-intuitive, but recall that `return nil` is just as much of a special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax because the initializer notionally has no return value. Personally, I have always disliked `return nil` in failable initializers for that reason, but I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because, in the case of a failable initializer, `return nil` continues to have the same meaning if we consider the return value of the initializer to be of type `Self?`. For that reason, I think your idea #2 is quite clever, and it would go a long way in making `return nil` a lot less odd. It also increases the expressivity of initializers because it allows one to set the value of self and also return in one statement, clearly demonstrating the intention that no other code in the initializer should be run before returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with initialization semantics, it provides more uniform syntax and it's a bit less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more cumbersome. Implicitly unwrapped optionals are a bit difficult, but this "variation" of it is much more restrictive then the normal ones, because unlike normal implicitly unwrapped optionals, this one cannot be accessed after being assigned nil (and it also cannot be indirectly assigned `nil`, because escaping `self` is not allowed before full initialization), so there is only one possible place it can be set to nil and that's directly in the initializer. This means that `self` can be safely treated as `inout Self` before being set to nil (and after being set to nil, it doesn't matter any more because you aren't allowed to access it, due to not being fully initialized).

I have to say, I don’t like either of these explanations at all. I think having a “special” IUO is a difficult sell; it is just conceptually too complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language wonkier because it currently has a parallel wonky feature in `return nil` seems like the wrong way to go. In addition, there’s nothing gained here that cannot be done with a defer statement; of course, defer statements might not be very elegant, but it would certainly be less wonky than inventing a new variation on an IUO to allow assignment of nil to self... For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic and the restrictions of `self as inout Self!` are imposed by already existing and well-understood initialization logic, so the provided guarantees don't really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
I think a good approach would be to have `self = nil` only mean `the initializer is going to fail` because if your type is ExpressibleByNilLiteral, it means that the `nil` of your type already carries the same meaning as if your type was not ExpressibleByNilLiteral and was an optional instead, so having a failable initializer doesn't really make sense in that case (since you could've initialized `self` to its own `nil` in case of failure). Still, some valid use cases may exist, so the natural (and quite intuitive) way to circumvent this would be to call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different thing in an initializer than it does in a function? Essentially, then, you’re creating your own variation on an implicitly unwrapped optional, where `self` is of type `inout Self?` for assignment in initializers only but not for any other purpose. Implicitly unwrapped optionals are hard to reason about, and having a variation on it would be even harder to understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however, I do think Greg is right that it would create more boilerplate than the current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
The type of `self` could remain `inout Self` inside the failable initializer. The ability to assign nil would be a compiler magic (much like `return nil` is compiler magic) that is meant to introduce uniformity to the initialization logic.

The idea is to define all different ways initialization can take place and expand them to be used uniformly on both `self` and all its members, as well as remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
  1. delegating initializer
  2. assigning to self
  3. returning nil

#1: The delegating initializer is pretty much perfect at this point, in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside failable initializers.

#3: The only thing that can be returned from an initializer is `nil`, which is compiler magic, so we can thing of it as a misnomer (because we aren't really **returning** anything).

If, for a second, we forget about potential factory initializers, returning anything from an initializer doesn't make much sense, because an initializer is conceptually meant to bring an existing object in memory to a type-specific valid state. This semantic was very explicitly in Objective-C with `[[MyType alloc] init]`. Especially since even syntactically, the initializer does not specify any return type, the idea of returning from an initializer is counter-intuitive both syntactically and semantically.

The actual *behavior* of `return nil` is very sensible, so the behavior, I imagine `self = nil`, would largely mean the same (except not needed to return immediately and allowing non-self-accessing code to be executed before return). Being able to assign `nil` to a non-optional (ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to initialize self to nil? That is what `self = nil` means if `self` is of type `inout Self`. If `self` is of type `inout Self` and Self is not ExpressibleByNilLiteral, then it must be an error to assign nil to self. Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to initialize an object in-place and doesn't look like it should return anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init` syntax could completely flip this logic, but making the initializer essentially a static function that returns an object. In this case the initializer could be made to specify the return type (that is the supertype of all possible factory-created objects) and assigning to self would be forbidden because there is not self yet:

extension MyProtocol {

  public factory init(weCool: Bool) -> MyProtocol {
    self = MyImpl() // error: cannot assign to `self` in a factory initializer
    self.init(...) // error: cannot make a delegating initializer call in a factory initializer
    if weCool {
      return MyCoolImpl()
    } else {
      return MyUncoolImpl()
    }
  }

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2 (as in `self.member = value`), which could be extended in a non-factory initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while giving a more reliable performance guarantee that this member will not be copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

If `self` is not of type `inout Self?`, then what is the type of `self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms to `ExpressibleByNilLiteral`, in which case you are able to assign `self = nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped optionals are no longer their own type, I’m not sure that’s possible. But even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self` would have to be of type `inout Self?`–which is intriguing but potentially more boilerplatey than the status quo.
On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and since `self` can only be initialized once, this would mean that after `self = nil`, you won't be allowed to access `self` in your initializer at all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to treat `self` as `inout Self?`, because the only place it can be `nil` is the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com <mailto:gparker@apple.com>> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable initializers (essentially making `self` look like `inout Self?` instead of `inout Self` with magical `return nil`), so that all initializers uniformly can be written in `self = ...` form for clarity and convenience purposes. This should, theoretically, be nothing but a `defer { return nil }` type of rewrite, so I don't see any major difficulties implementing this. This is especially useful for failable-initializing enums where the main switch simply assigns to self in all cases and the rest of the initializer does some post-processing.

I don't see how to avoid source incompatibility and uglification of failable initializer implementations here. Allowing `self = nil` inside a failable initializer would require `self` to be an optional. That in turn would require every use of `self` in the initializer to be nil-checked or forced. I don't think that loss everywhere outweighs the gain of `self = nil` in some places.

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler

_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
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

I just didn't want to use the commonly proposed `factory` word, because it implies a specific semantic tied to the factory method pattern.
I gave it another thought and I'm thinking maybe we can forego the annotation and have the compiler deduce it automatically.
There are only two places where an indirect initializer can exist:
* Protocol extensions, returning a conforming type.
* Classes, returning an instance.
It doesn't make sense to have this on value types, since they do not have subtypes of any kind.
Indirect initializers are very unambiguous in protocol extensions, because the only other way of implementing an initializer in a protocol extension is via delegating initialization, so the indirect-ness of the initializer can be statically determined by whether or not there is a delegating initializer involved.
If the initializer in a protocol extension has a delegating initialization on any execution path, then returning an instance is disallowed and vice versa. This will ensure strict separation of initializer types for the compiler to generate code for.
If a failable initializer in a protocol extension unconditionally returns `nil`, then no initialization takes place anyway, so it doesn't matter, which one the compiler chooses.
In classes this is a bit difficult, because besides delegating initializers, they also can initialize the members directly.
So, in addition to the distinguishing rule for the protocol extensions, classes will also check whether any member is assigned to on any execution path.

What do you think?

···

On Jun 11, 2017, at 5:53 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Sun, Jun 11, 2017 at 8:49 AM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
Can you recall the reasons why the removal of access modifiers on extensions was rejected?

It was an unassailable reason, really: people found this shorthand useful and wanted to continue to use it--it is the only way to specify that multiple members are public without explicitly labeling each one. The core team agreed it was useful.

My takeaway from the whole episode (I was greatly in favor of removing this shorthand, as it's highly inconsistent with all other access modifier rules) is that in general, since the bar for new syntax is so high, if a shorthand made it into the language (and especially if it's kind of an inconsistent shorthand) the general presumption must be that it is highly desired.

Also, do you think `indirect init` is confusing inside an `indirect enum`?

I do. These are unrelated definitions of "indirect," and I'm puzzled why you'd actively choose to run into issues with the same word meaning two things when you could choose another word.

On Jun 11, 2017, at 4:40 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Removal of access modifiers on extensions has been proposed, reviewed, and rejected, so that’s that.

In general, Swift uses distinct keywords for distinct concepts, unlike Rust which likes to reuse keywords in clever ways; if you’re finding that things are getting confusing with one word meaning two things, that shouldn’t be an invitation to rip out existing syntax but is probably a good sign you shouldn’t be repurposing that keyword.

On Sun, Jun 11, 2017 at 03:28 Adrian Zubarev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Yeah, well I messed up my proposal from last year about removing the access modifier on extensions and wish now I wasn’t that confused back than and made it right.

The indirect keyword is literally the same story. The docs only says that this is only a shortcut.

„To enable indirection for all the cases of an enumeration, mark the entire enumeration with the indirect modifier—this is convenient when the enumeration contains many cases that would each need to be marked with the indirect modifier.“

If you really wish to reuse that keyword here we might need to remove such shortcuts from the language (indirect enum, access modifier on extensions, anything else?).

--
Adrian Zubarev
Sent with Airmail

Am 11. Juni 2017 um 10:12:38, Gor Gyolchanyan (gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>) schrieb:

I always wondered, why is `indirect` allowed on the `enum` itself? Wouldn't it make more sense to apply it to individual cases that recursively refer to the `enum`?
This question also applies to access modifiers on extensions. So, what is it supposed to do? Change the default access modifier from `internal` to whatever I specify? That's just confusing, reduces readability and the syntactic gain is marginal at best.
If the `indirect` confusion becomes real, I'd suggest getting rid of `indirect enum` and using `indirect case` instead.

On Jun 11, 2017, at 11:05 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

The proposal is looking good to me. :) It will also enable easy support for custom views using XIBs in iOS development without unnecessary view nesting.

For instance the function from this example ios - Loading a XIB file to a UIView Swift - Stack Overflow could be used directly inside an init:

class MyView : UIView {
      
      indirect init() {
            return MyView.instantiateFromXib()
            // Or after SR-0068
            return Self.instantiateFromXib()
      }
}
There is still one little thing that bothers me, it might be a little bit confusing to have two different meanings of indirect on enums.

indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)
      
    // This might makes no sense, but it would still be possible after
    // this proposal.
    indirect init(other: ArithmeticExpression) {
       return other
    }
      
    // Furthermore if the keyboard is applied to the enum
    // directly all other `indirect` uses are inferred.
    // Will this be implicitly `indirect` because of the previous fact?
    init() { … }
}

--
Adrian Zubarev
Sent with Airmail

Am 11. Juni 2017 um 00:38:56, Riley Testut via swift-evolution (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) schrieb:

Awesome! Updated my proposal to include what I believed to be the relevant portions of your indirect initializer idea. Let me know if there’s anything I missed or should change :-)

https://github.com/rileytestut/swift-evolution/blob/master/proposals/NNNN-factory-initializers.md

On Jun 10, 2017, at 12:43 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:

Hi, Riley!

I think that's a great idea! We can merge the second part of my proposal (the `indirect init`) into your one and refine and consolidate the prerequisite proposal (about returning from `init` and possibly in-place member initializers) and bunch them up into a proposal cluster (the way swift coders did).
Feel free to tear out any chunks from my proposal, while I think about a more in-depth rationale about revamping initialization syntax. :slightly_smiling_face:

On Jun 10, 2017, at 8:36 PM, Riley Testut <rileytestut@gmail.com <mailto:rileytestut@gmail.com>> wrote:

Hi Gor :wave:

I’m very much in fan of a unified initialization syntax. I submitted my own proposal for factory initializers a while back, but since it wasn’t a focus of Swift 3 or 4 I haven’t followed up on it recently. In the time since last working on it, I came to my own conclusion that rather than focusing on factory initialization, the overall initialization process should be simplified, which I’m glad to see someone else has realized as well :-)

Here’s my proposal for reference: Proposal: Factory Initializers by rileytestut · Pull Request #247 · apple/swift-evolution · GitHub Originally I used the “factory” keyword, but I think your “indirect” keyword may be a better fit (since it has precedent in the language and is not limited to “just” being about factory initialization). To divide your proposal up into smaller pieces for review, maybe we could update my proposal to use your indirect keyword, and then start a separate topic/proposal for the remaining aspects of your proposal? I agree that splitting it into smaller chunks may be better for the process.

Let me know what you think!

Riley

On Jun 10, 2017, at 3:33 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This is a very interesting read.

Thanks you! I tried to make it as clear and detailed as possible. :slightly_smiling_face:

We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

I was writing the proposal and was just about to write `factory init`, when it occurred to me: enums already have a keyword that does something very similar. It seemed to me that an initializer that doesn't initialize the instance in-place, but returns a completely separate instance from somewhere else, is kinda "indirectly" initializing the instance. Plus, the already established keyword and its semantic would reduce the learning curve for this new feature and separate it from a single specific use case (the "factory method" pattern).

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

I think the `return` can be easily implemented first, while opening up an opportunity to later implement `indirect init`. The reason why I unified them was that the `return` idea on its own has very limited merit and could the thought of as a low-priority cosmetic enhancement. I wouldn't want it to be viewed that way because the primary purpose of that idea is to enable `indirect init` (which Cocoa and Cocoa Touch developers would be very happy about).

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

Very good point. The challenge is to correctly separate them, without losing context in their respective proposals and without bleeding the proposals into each other.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

I'd never send a pull request to swift-evolution without thoroughly discussing it here. I just though, if I'm going to write a whole proposal with examples and motivation, it would be easier to demonstrate it and discuss in with the community If I just went ahead and wrote the whole thing and sent the link. This way it would be clearer to the reader and the discussed changes would be accurately reflected by the commits I'd make to my proposal.

Original Message

On Jun 10, 2017, at 2:38 AM, Daryle Walker via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/master/proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed it wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

This is a very interesting read. We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Cool. I have reservations about idea #3, but we can tackle that another day. (Real life things beckon.) But suffice it to say that I now really, really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self` non-optional.
This would make `return nil` less out-of-place, like you said, while still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax, while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it to change the signature as well as remove any compiler assumptions about the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
So far, we've discussed two ways of interpreting `self = nil`, both of which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as counter-intuitive, but recall that `return nil` is just as much of a special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax because the initializer notionally has no return value. Personally, I have always disliked `return nil` in failable initializers for that reason, but I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because, in the case of a failable initializer, `return nil` continues to have the same meaning if we consider the return value of the initializer to be of type `Self?`. For that reason, I think your idea #2 is quite clever, and it would go a long way in making `return nil` a lot less odd. It also increases the expressivity of initializers because it allows one to set the value of self and also return in one statement, clearly demonstrating the intention that no other code in the initializer should be run before returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with initialization semantics, it provides more uniform syntax and it's a bit less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more cumbersome. Implicitly unwrapped optionals are a bit difficult, but this "variation" of it is much more restrictive then the normal ones, because unlike normal implicitly unwrapped optionals, this one cannot be accessed after being assigned nil (and it also cannot be indirectly assigned `nil`, because escaping `self` is not allowed before full initialization), so there is only one possible place it can be set to nil and that's directly in the initializer. This means that `self` can be safely treated as `inout Self` before being set to nil (and after being set to nil, it doesn't matter any more because you aren't allowed to access it, due to not being fully initialized).

I have to say, I don’t like either of these explanations at all. I think having a “special” IUO is a difficult sell; it is just conceptually too complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language wonkier because it currently has a parallel wonky feature in `return nil` seems like the wrong way to go. In addition, there’s nothing gained here that cannot be done with a defer statement; of course, defer statements might not be very elegant, but it would certainly be less wonky than inventing a new variation on an IUO to allow assignment of nil to self... For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic and the restrictions of `self as inout Self!` are imposed by already existing and well-understood initialization logic, so the provided guarantees don't really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
I think a good approach would be to have `self = nil` only mean `the initializer is going to fail` because if your type is ExpressibleByNilLiteral, it means that the `nil` of your type already carries the same meaning as if your type was not ExpressibleByNilLiteral and was an optional instead, so having a failable initializer doesn't really make sense in that case (since you could've initialized `self` to its own `nil` in case of failure). Still, some valid use cases may exist, so the natural (and quite intuitive) way to circumvent this would be to call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different thing in an initializer than it does in a function? Essentially, then, you’re creating your own variation on an implicitly unwrapped optional, where `self` is of type `inout Self?` for assignment in initializers only but not for any other purpose. Implicitly unwrapped optionals are hard to reason about, and having a variation on it would be even harder to understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however, I do think Greg is right that it would create more boilerplate than the current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
The type of `self` could remain `inout Self` inside the failable initializer. The ability to assign nil would be a compiler magic (much like `return nil` is compiler magic) that is meant to introduce uniformity to the initialization logic.

The idea is to define all different ways initialization can take place and expand them to be used uniformly on both `self` and all its members, as well as remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
1. delegating initializer
2. assigning to self
3. returning nil

#1: The delegating initializer is pretty much perfect at this point, in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside failable initializers.

#3: The only thing that can be returned from an initializer is `nil`, which is compiler magic, so we can thing of it as a misnomer (because we aren't really **returning** anything).

If, for a second, we forget about potential factory initializers, returning anything from an initializer doesn't make much sense, because an initializer is conceptually meant to bring an existing object in memory to a type-specific valid state. This semantic was very explicitly in Objective-C with `[[MyType alloc] init]`. Especially since even syntactically, the initializer does not specify any return type, the idea of returning from an initializer is counter-intuitive both syntactically and semantically.

The actual *behavior* of `return nil` is very sensible, so the behavior, I imagine `self = nil`, would largely mean the same (except not needed to return immediately and allowing non-self-accessing code to be executed before return). Being able to assign `nil` to a non-optional (ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to initialize self to nil? That is what `self = nil` means if `self` is of type `inout Self`. If `self` is of type `inout Self` and Self is not ExpressibleByNilLiteral, then it must be an error to assign nil to self. Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to initialize an object in-place and doesn't look like it should return anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init` syntax could completely flip this logic, but making the initializer essentially a static function that returns an object. In this case the initializer could be made to specify the return type (that is the supertype of all possible factory-created objects) and assigning to self would be forbidden because there is not self yet:

extension MyProtocol {

public factory init(weCool: Bool) -> MyProtocol {
self = MyImpl() // error: cannot assign to `self` in a factory initializer
self.init(...) // error: cannot make a delegating initializer call in a factory initializer
if weCool {
return MyCoolImpl()
} else {
return MyUncoolImpl()
}
}

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2 (as in `self.member = value`), which could be extended in a non-factory initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while giving a more reliable performance guarantee that this member will not be copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

If `self` is not of type `inout Self?`, then what is the type of `self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms to `ExpressibleByNilLiteral`, in which case you are able to assign `self = nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped optionals are no longer their own type, I’m not sure that’s possible. But even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self` would have to be of type `inout Self?`–which is intriguing but potentially more boilerplatey than the status quo.
On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and since `self` can only be initialized once, this would mean that after `self = nil`, you won't be allowed to access `self` in your initializer at all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to treat `self` as `inout Self?`, because the only place it can be `nil` is the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com <mailto:gparker@apple.com>> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable initializers (essentially making `self` look like `inout Self?` instead of `inout Self` with magical `return nil`), so that all initializers uniformly can be written in `self = ...` form for clarity and convenience purposes. This should, theoretically, be nothing but a `defer { return nil }` type of rewrite, so I don't see any major difficulties implementing this. This is especially useful for failable-initializing enums where the main switch simply assigns to self in all cases and the rest of the initializer does some post-processing.

I don't see how to avoid source incompatibility and uglification of failable initializer implementations here. Allowing `self = nil` inside a failable initializer would require `self` to be an optional. That in turn would require every use of `self` in the initializer to be nil-checked or forced. I don't think that loss everywhere outweighs the gain of `self = nil` in some places.

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler

_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

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

Yeah, well I messed up my proposal from last year about removing the access modifier on extensions and wish now I wasn’t that confused back than and made it right.

The indirect keyword is literally the same story. The docs only says that this is only a shortcut.

„To enable indirection for all the cases of an enumeration, mark the entire enumeration with the indirect modifier—this is convenient when the enumeration contains many cases that would each need to be marked with the indirect modifier.“
If you really wish to reuse that keyword here we might need to remove such shortcuts from the language (indirect enum, access modifier on extensions, anything else?).

···

--
Adrian Zubarev
Sent with Airmail

Am 11. Juni 2017 um 10:12:38, Gor Gyolchanyan (gor@gyolchanyan.com) schrieb:

I always wondered, why is `indirect` allowed on the `enum` itself? Wouldn't it make more sense to apply it to individual cases that recursively refer to the `enum`?
This question also applies to access modifiers on extensions. So, what is it supposed to do? Change the default access modifier from `internal` to whatever I specify? That's just confusing, reduces readability and the syntactic gain is marginal at best.
If the `indirect` confusion becomes real, I'd suggest getting rid of `indirect enum` and using `indirect case` instead.

On Jun 11, 2017, at 11:05 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org> wrote:

The proposal is looking good to me. :) It will also enable easy support for custom views using XIBs in iOS development without unnecessary view nesting.

For instance the function from this example ios - Loading a XIB file to a UIView Swift - Stack Overflow could be used directly inside an init:

class MyView : UIView {
      
      indirect init() {
            return MyView.instantiateFromXib()
            // Or after SR-0068
            return Self.instantiateFromXib()
      }
}
There is still one little thing that bothers me, it might be a little bit confusing to have two different meanings of indirect on enums.

indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)
      
    // This might makes no sense, but it would still be possible after
    // this proposal.
    indirect init(other: ArithmeticExpression) {
       return other
    }
      
    // Furthermore if the keyboard is applied to the enum
    // directly all other `indirect` uses are inferred.
    // Will this be implicitly `indirect` because of the previous fact?
    init() { … }
}

--
Adrian Zubarev
Sent with Airmail

Am 11. Juni 2017 um 00:38:56, Riley Testut via swift-evolution (swift-evolution@swift.org) schrieb:

Awesome! Updated my proposal to include what I believed to be the relevant portions of your indirect initializer idea. Let me know if there’s anything I missed or should change :-)

On Jun 10, 2017, at 12:43 PM, Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

Hi, Riley!

I think that's a great idea! We can merge the second part of my proposal (the `indirect init`) into your one and refine and consolidate the prerequisite proposal (about returning from `init` and possibly in-place member initializers) and bunch them up into a proposal cluster (the way swift coders did).
Feel free to tear out any chunks from my proposal, while I think about a more in-depth rationale about revamping initialization syntax. :slightly_smiling_face:

On Jun 10, 2017, at 8:36 PM, Riley Testut <rileytestut@gmail.com> wrote:

Hi Gor :wave:

I’m very much in fan of a unified initialization syntax. I submitted my own proposal for factory initializers a while back, but since it wasn’t a focus of Swift 3 or 4 I haven’t followed up on it recently. In the time since last working on it, I came to my own conclusion that rather than focusing on factory initialization, the overall initialization process should be simplified, which I’m glad to see someone else has realized as well :-)

Here’s my proposal for reference: Proposal: Factory Initializers by rileytestut · Pull Request #247 · apple/swift-evolution · GitHub Originally I used the “factory” keyword, but I think your “indirect” keyword may be a better fit (since it has precedent in the language and is not limited to “just” being about factory initialization). To divide your proposal up into smaller pieces for review, maybe we could update my proposal to use your indirect keyword, and then start a separate topic/proposal for the remaining aspects of your proposal? I agree that splitting it into smaller chunks may be better for the process.

Let me know what you think!

Riley

On Jun 10, 2017, at 3:33 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org> wrote:

This is a very interesting read.

Thanks you! I tried to make it as clear and detailed as possible. :slightly_smiling_face:

We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

I was writing the proposal and was just about to write `factory init`, when it occurred to me: enums already have a keyword that does something very similar. It seemed to me that an initializer that doesn't initialize the instance in-place, but returns a completely separate instance from somewhere else, is kinda "indirectly" initializing the instance. Plus, the already established keyword and its semantic would reduce the learning curve for this new feature and separate it from a single specific use case (the "factory method" pattern).

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

I think the `return` can be easily implemented first, while opening up an opportunity to later implement `indirect init`. The reason why I unified them was that the `return` idea on its own has very limited merit and could the thought of as a low-priority cosmetic enhancement. I wouldn't want it to be viewed that way because the primary purpose of that idea is to enable `indirect init` (which Cocoa and Cocoa Touch developers would be very happy about).

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

Very good point. The challenge is to correctly separate them, without losing context in their respective proposals and without bleeding the proposals into each other.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

I'd never send a pull request to swift-evolution without thoroughly discussing it here. I just though, if I'm going to write a whole proposal with examples and motivation, it would be easier to demonstrate it and discuss in with the community If I just went ahead and wrote the whole thing and sent the link. This way it would be clearer to the reader and the discussed changes would be accurately reflected by the commits I'd make to my proposal.

Original Message

On Jun 10, 2017, at 2:38 AM, Daryle Walker via swift-evolution <swift-evolution@swift.org> wrote:

On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <gor@gyolchanyan.com> wrote:
Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/master/proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed it wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

This is a very interesting read. We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Cool. I have reservations about idea #3, but we can tackle that another day. (Real life things beckon.) But suffice it to say that I now really, really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:
You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self` non-optional.
This would make `return nil` less out-of-place, like you said, while still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax, while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it to change the signature as well as remove any compiler assumptions about the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:
So far, we've discussed two ways of interpreting `self = nil`, both of which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as counter-intuitive, but recall that `return nil` is just as much of a special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax because the initializer notionally has no return value. Personally, I have always disliked `return nil` in failable initializers for that reason, but I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because, in the case of a failable initializer, `return nil` continues to have the same meaning if we consider the return value of the initializer to be of type `Self?`. For that reason, I think your idea #2 is quite clever, and it would go a long way in making `return nil` a lot less odd. It also increases the expressivity of initializers because it allows one to set the value of self and also return in one statement, clearly demonstrating the intention that no other code in the initializer should be run before returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with initialization semantics, it provides more uniform syntax and it's a bit less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more cumbersome. Implicitly unwrapped optionals are a bit difficult, but this "variation" of it is much more restrictive then the normal ones, because unlike normal implicitly unwrapped optionals, this one cannot be accessed after being assigned nil (and it also cannot be indirectly assigned `nil`, because escaping `self` is not allowed before full initialization), so there is only one possible place it can be set to nil and that's directly in the initializer. This means that `self` can be safely treated as `inout Self` before being set to nil (and after being set to nil, it doesn't matter any more because you aren't allowed to access it, due to not being fully initialized).

I have to say, I don’t like either of these explanations at all. I think having a “special” IUO is a difficult sell; it is just conceptually too complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language wonkier because it currently has a parallel wonky feature in `return nil` seems like the wrong way to go. In addition, there’s nothing gained here that cannot be done with a defer statement; of course, defer statements might not be very elegant, but it would certainly be less wonky than inventing a new variation on an IUO to allow assignment of nil to self... For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic and the restrictions of `self as inout Self!` are imposed by already existing and well-understood initialization logic, so the provided guarantees don't really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:
I think a good approach would be to have `self = nil` only mean `the initializer is going to fail` because if your type is ExpressibleByNilLiteral, it means that the `nil` of your type already carries the same meaning as if your type was not ExpressibleByNilLiteral and was an optional instead, so having a failable initializer doesn't really make sense in that case (since you could've initialized `self` to its own `nil` in case of failure). Still, some valid use cases may exist, so the natural (and quite intuitive) way to circumvent this would be to call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different thing in an initializer than it does in a function? Essentially, then, you’re creating your own variation on an implicitly unwrapped optional, where `self` is of type `inout Self?` for assignment in initializers only but not for any other purpose. Implicitly unwrapped optionals are hard to reason about, and having a variation on it would be even harder to understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however, I do think Greg is right that it would create more boilerplate than the current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:
The type of `self` could remain `inout Self` inside the failable initializer. The ability to assign nil would be a compiler magic (much like `return nil` is compiler magic) that is meant to introduce uniformity to the initialization logic.

The idea is to define all different ways initialization can take place and expand them to be used uniformly on both `self` and all its members, as well as remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
1. delegating initializer
2. assigning to self
3. returning nil

#1: The delegating initializer is pretty much perfect at this point, in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside failable initializers.

#3: The only thing that can be returned from an initializer is `nil`, which is compiler magic, so we can thing of it as a misnomer (because we aren't really **returning** anything).

If, for a second, we forget about potential factory initializers, returning anything from an initializer doesn't make much sense, because an initializer is conceptually meant to bring an existing object in memory to a type-specific valid state. This semantic was very explicitly in Objective-C with `[[MyType alloc] init]`. Especially since even syntactically, the initializer does not specify any return type, the idea of returning from an initializer is counter-intuitive both syntactically and semantically.

The actual *behavior* of `return nil` is very sensible, so the behavior, I imagine `self = nil`, would largely mean the same (except not needed to return immediately and allowing non-self-accessing code to be executed before return). Being able to assign `nil` to a non-optional (ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to initialize self to nil? That is what `self = nil` means if `self` is of type `inout Self`. If `self` is of type `inout Self` and Self is not ExpressibleByNilLiteral, then it must be an error to assign nil to self. Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to initialize an object in-place and doesn't look like it should return anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init` syntax could completely flip this logic, but making the initializer essentially a static function that returns an object. In this case the initializer could be made to specify the return type (that is the supertype of all possible factory-created objects) and assigning to self would be forbidden because there is not self yet:

extension MyProtocol {

public factory init(weCool: Bool) -> MyProtocol {
self = MyImpl() // error: cannot assign to `self` in a factory initializer
self.init(...) // error: cannot make a delegating initializer call in a factory initializer
if weCool {
return MyCoolImpl()
} else {
return MyUncoolImpl()
}
}

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2 (as in `self.member = value`), which could be extended in a non-factory initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while giving a more reliable performance guarantee that this member will not be copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

If `self` is not of type `inout Self?`, then what is the type of `self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms to `ExpressibleByNilLiteral`, in which case you are able to assign `self = nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped optionals are no longer their own type, I’m not sure that’s possible. But even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self` would have to be of type `inout Self?`–which is intriguing but potentially more boilerplatey than the status quo.
On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org> wrote:
Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and since `self` can only be initialized once, this would mean that after `self = nil`, you won't be allowed to access `self` in your initializer at all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to treat `self` as `inout Self?`, because the only place it can be `nil` is the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable initializers (essentially making `self` look like `inout Self?` instead of `inout Self` with magical `return nil`), so that all initializers uniformly can be written in `self = ...` form for clarity and convenience purposes. This should, theoretically, be nothing but a `defer { return nil }` type of rewrite, so I don't see any major difficulties implementing this. This is especially useful for failable-initializing enums where the main switch simply assigns to self in all cases and the rest of the initializer does some post-processing.

I don't see how to avoid source incompatibility and uglification of failable initializer implementations here. Allowing `self = nil` inside a failable initializer would require `self` to be an optional. That in turn would require every use of `self` in the initializer to be nil-checked or forced. I don't think that loss everywhere outweighs the gain of `self = nil` in some places.

--
Greg Parker gparker@apple.com Runtime Wrangler

_______________________________________________
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

_______________________________________________
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

I just didn't want to use the commonly proposed `factory` word, because it
implies a specific semantic tied to the factory method pattern.
I gave it another thought and I'm thinking maybe we can forego the
annotation and have the compiler deduce it automatically.
There are only two places where an indirect initializer can exist:
* Protocol extensions, returning a conforming type.
* Classes, returning an instance.
It doesn't make sense to have this on value types, since they do not have
subtypes of any kind.
Indirect initializers are very unambiguous in protocol extensions, because
the only other way of implementing an initializer in a protocol extension
is via delegating initialization, so the indirect-ness of the initializer
can be statically determined by whether or not there is a delegating
initializer involved.
If the initializer in a protocol extension has a delegating initialization
on any execution path, then returning an instance is disallowed and vice
versa. This will ensure strict separation of initializer types for the
compiler to generate code for.
If a failable initializer in a protocol extension unconditionally returns
`nil`, then no initialization takes place anyway, so it doesn't matter,
which one the compiler chooses.
In classes this is a bit difficult, because besides delegating
initializers, they also can initialize the members directly.
So, in addition to the distinguishing rule for the protocol extensions,
classes will also check whether any member is assigned to on any execution
path.

What do you think?

Keywords aren't just for the compiler; they're for the human reader too! If
you believe the use of your proposed feature in protocol extensions is
unambiguous to humans as well as compilers, then IMO it makes sense not to
require another keyword in that place. I haven't thought deeply about
whether that would be the case.

Clearly, you're saying that this is a more complicated situation with
classes; I think it makes sense for you to consider requiring a keyword
there. There is precedent for keywords modifying `init` to be required for
classes but not for value types (e.g., `convenience`).

Regardless of whether a keyword is required or not, your feature needs a
name. And here again, I think it is puzzling that you are calling them
"indirect initializers" when there is already another meaning for
"indirect" in Swift. Distinct concepts should have distinct names.

···

On Sun, Jun 11, 2017 at 10:34 AM, Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

On Jun 11, 2017, at 5:53 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Sun, Jun 11, 2017 at 8:49 AM, Gor Gyolchanyan <gor@gyolchanyan.com> > wrote:

Can you recall the reasons why the removal of access modifiers on
extensions was rejected?

It was an unassailable reason, really: people found this shorthand useful
and wanted to continue to use it--it is the only way to specify that
multiple members are public without explicitly labeling each one. The core
team agreed it was useful.

My takeaway from the whole episode (I was greatly in favor of removing
this shorthand, as it's highly inconsistent with all other access modifier
rules) is that in general, since the bar for new syntax is so high, if a
shorthand made it into the language (and especially if it's kind of an
inconsistent shorthand) the general presumption must be that it is highly
desired.

Also, do you think `indirect init` is confusing inside an `indirect enum`?

I do. These are unrelated definitions of "indirect," and I'm puzzled why
you'd actively choose to run into issues with the same word meaning two
things when you could choose another word.

On Jun 11, 2017, at 4:40 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Removal of access modifiers on extensions has been proposed, reviewed,
and rejected, so that’s that.

In general, Swift uses distinct keywords for distinct concepts, unlike
Rust which likes to reuse keywords in clever ways; if you’re finding that
things are getting confusing with one word meaning two things, that
shouldn’t be an invitation to rip out existing syntax but is probably a
good sign you shouldn’t be repurposing that keyword.

On Sun, Jun 11, 2017 at 03:28 Adrian Zubarev via swift-evolution < >> swift-evolution@swift.org> wrote:

Yeah, well I messed up my proposal from last year about removing the
access modifier on extensions and wish now I wasn’t that confused back than
and made it right.

The indirect keyword is literally the same story. The docs only says
that this is only a shortcut.

„To enable indirection for all the cases of an enumeration, mark the
entire enumeration with the indirect modifier—this is convenient when the
enumeration contains many cases that would each need to be marked with the
indirect modifier.“

If you really wish to reuse that keyword here we might need to remove
such shortcuts from the language (indirect enum, access modifier on
extensions, anything else?).

--
Adrian Zubarev
Sent with Airmail

Am 11. Juni 2017 um 10:12:38, Gor Gyolchanyan (gor@gyolchanyan.com)
schrieb:

I always wondered, why is `indirect` allowed on the `enum` itself?
Wouldn't it make more sense to apply it to individual cases that
recursively refer to the `enum`?
This question also applies to access modifiers on extensions. So, what
is it supposed to do? Change the default access modifier from `internal` to
whatever I specify? That's just confusing, reduces readability and the
syntactic gain is marginal at best.
If the `indirect` confusion becomes real, I'd suggest getting rid of
`indirect enum` and using `indirect case` instead.

On Jun 11, 2017, at 11:05 AM, Adrian Zubarev via swift-evolution < >>> swift-evolution@swift.org> wrote:

The proposal is looking good to me. :) It will also enable easy support
for custom views using XIBs in iOS development without unnecessary view
nesting.

For instance the function from this example https://stackoverflow.
com/a/43123783/4572536 could be used directly inside an init:

class MyView : UIView {

      indirect init() {
            return MyView.instantiateFromXib()
            // Or after SR-0068
            return Self.instantiateFromXib()
      }
}

There is still one little thing that bothers me, it might be a little
bit confusing to have two different meanings of indirect on enums.

indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)

    // This might makes no sense, but it would still be possible after
    // this proposal.
    indirect init(other: ArithmeticExpression) {
       return other
    }

    // Furthermore if the keyboard is applied to the enum
    // directly all other `indirect` uses are inferred.
    // Will this be implicitly `indirect` because of the previous fact?
    init() { … }
}

--
Adrian Zubarev
Sent with Airmail

Am 11. Juni 2017 um 00:38:56, Riley Testut via swift-evolution (
swift-evolution@swift.org) schrieb:

Awesome! Updated my proposal to include what I believed to be the
relevant portions of your indirect initializer idea. Let me know if there’s
anything I missed or should change :-)

https://github.com/rileytestut/swift-evolution/blob/master/p
roposals/NNNN-factory-initializers.md

On Jun 10, 2017, at 12:43 PM, Gor Gyolchanyan <gor@gyolchanyan.com> >>> wrote:

Hi, Riley!

I think that's a great idea! We can merge the second part of my proposal
(the `indirect init`) into your one and refine and consolidate the
prerequisite proposal (about returning from `init` and possibly in-place
member initializers) and bunch them up into a proposal cluster (the way
swift coders did).
Feel free to tear out any chunks from my proposal, while I think about a
more in-depth rationale about revamping initialization syntax. :slightly_smiling_face:

On Jun 10, 2017, at 8:36 PM, Riley Testut <rileytestut@gmail.com> wrote:

Hi Gor :wave:

I’m very much in fan of a unified initialization syntax. I submitted my
own proposal for factory initializers a while back, but since it wasn’t a
focus of Swift 3 or 4 I haven’t followed up on it recently. In the time
since last working on it, I came to my own conclusion that rather than
focusing on factory initialization, the overall initialization process
should be simplified, which I’m glad to see someone else has realized as
well :-)

Here’s my proposal for reference: https://github.com/
apple/swift-evolution/pull/247/commits/58b5a93b322aae998eb40
574dee15fe54323de2e Originally I used the “factory” keyword, but I
think your “indirect” keyword may be a better fit (since it has precedent
in the language and is not limited to “just” being about factory
initialization). To divide your proposal up into smaller pieces for review,
maybe we could update my proposal to use your indirect keyword, and then
start a separate topic/proposal for the remaining aspects of your proposal?
I agree that splitting it into smaller chunks may be better for the process.

Let me know what you think!

Riley

On Jun 10, 2017, at 3:33 AM, Gor Gyolchanyan via swift-evolution < >>> swift-evolution@swift.org> wrote:

This is a very interesting read.

Thanks you! I tried to make it as clear and detailed as possible. :slightly_smiling_face:

We did not discuss the 'indirect' idea at all on this list. Did you come
up with it just now? In any case, my suggestion as to moving forward would
be this:

I was writing the proposal and was just about to write `factory init`,
when it occurred to me: enums already have a keyword that does something
very similar. It seemed to me that an initializer that doesn't initialize
the instance in-place, but returns a completely separate instance from
somewhere else, is kinda "indirectly" initializing the instance. Plus, the
already established keyword and its semantic would reduce the learning
curve for this new feature and separate it from a single specific use case
(the "factory method" pattern).

- Do you feel that both halves of your draft (expanding `return` in
initializers, and `indirect` initializers) should absolutely be one
proposal, or can they be separated?

I think the `return` can be easily implemented first, while opening up
an opportunity to later implement `indirect init`. The reason why I unified
them was that the `return` idea on its own has very limited merit and could
the thought of as a low-priority cosmetic enhancement. I wouldn't want it
to be viewed that way because the primary purpose of that idea is to enable
`indirect init` (which Cocoa and Cocoa Touch developers would be very happy
about).

a) If they can be separated because each half has individual merit, then
these ideas may be more likely to succeed as separate proposals, as each
can be critiqued fully and judged independently as digestible units.

Very good point. The challenge is to correctly separate them, without
losing context in their respective proposals and without bleeding the
proposals into each other.

b) If you intend to tackle all your ideas all at once, that's going to
be a much bigger change--in terms of review effort, likely bikeshedding,
and implementation effort. It'll probably be best to solicit initial
feedback on this list first about `indirect` initializers, even if just to
familiarize the community with the idea, before launching into a pitch of
the whole proposal.

I'd never send a pull request to swift-evolution without thoroughly
discussing it here. I just though, if I'm going to write a whole proposal
with examples and motivation, it would be easier to demonstrate it and
discuss in with the community If I just went ahead and wrote the whole
thing and sent the link. This way it would be clearer to the reader and the
discussed changes would be accurately reflected by the commits I'd make to
my proposal.

Original Message

On Jun 10, 2017, at 2:38 AM, Daryle Walker via swift-evolution < >>> swift-evolution@swift.org> wrote:

On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <gor@gyolchanyan.com> >>> wrote:

Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/master/
proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed
it wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

This is a very interesting read. We did not discuss the 'indirect' idea
at all on this list. Did you come up with it just now? In any case, my
suggestion as to moving forward would be this:

- Do you feel that both halves of your draft (expanding `return` in
initializers, and `indirect` initializers) should absolutely be one
proposal, or can they be separated?

a) If they can be separated because each half has individual merit, then
these ideas may be more likely to succeed as separate proposals, as each
can be critiqued fully and judged independently as digestible units.

b) If you intend to tackle all your ideas all at once, that's going to
be a much bigger change--in terms of review effort, likely bikeshedding,
and implementation effort. It'll probably be best to solicit initial
feedback on this list first about `indirect` initializers, even if just to
familiarize the community with the idea, before launching into a pitch of
the whole proposal.

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Cool. I have reservations about idea #3, but we can tackle that another
day. (Real life things beckon.) But suffice it to say that I now really,
really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com> >>>> wrote:

You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the
signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are
non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self`
non-optional.
This would make `return nil` less out-of-place, like you said, while
still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax,
while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause
it to change the signature as well as remove any compiler assumptions about
the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic
in-place initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com> >>>>> wrote:

So far, we've discussed two ways of interpreting `self = nil`, both
of which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as
counter-intuitive, but recall that `return nil` is just as much of a
special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other
syntax because the initializer notionally has no return value. Personally,
I have always disliked `return nil` in failable initializers for that
reason, but I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting
because, in the case of a failable initializer, `return nil` continues to
have the same meaning if we consider the return value of the initializer to
be of type `Self?`. For that reason, I think your idea #2 is quite clever,
and it would go a long way in making `return nil` a lot less odd. It also
increases the expressivity of initializers because it allows one to set the
value of self and also return in one statement, clearly demonstrating the
intention that no other code in the initializer should be run before
returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with

initialization semantics, it provides more uniform syntax and it's a bit
less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more
cumbersome. Implicitly unwrapped optionals are a bit difficult, but this
"variation" of it is much more restrictive then the normal ones, because
unlike normal implicitly unwrapped optionals, this one cannot be accessed
after being assigned nil (and it also cannot be indirectly assigned `nil`,
because escaping `self` is not allowed before full initialization), so
there is only one possible place it can be set to nil and that's directly
in the initializer. This means that `self` can be safely treated as `inout
Self` before being set to nil (and after being set to nil, it doesn't
matter any more because you aren't allowed to access it, due to not being
fully initialized).

I have to say, I don’t like either of these explanations at all. I
think having a “special” IUO is a difficult sell; it is just conceptually
too complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language
wonkier because it currently has a parallel wonky feature in `return nil`
seems like the wrong way to go. In addition, there’s nothing gained here
that cannot be done with a defer statement; of course, defer statements
might not be very elegant, but it would certainly be less wonky than
inventing a new variation on an IUO to allow assignment of nil to self...
For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic

and the restrictions of `self as inout Self!` are imposed by already
existing and well-understood initialization logic, so the provided
guarantees don't really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com> >>>>>> wrote:

I think a good approach would be to have `self = nil` only mean `the
initializer is going to fail` because if your type is
ExpressibleByNilLiteral, it means that the `nil` of your type already
carries the same meaning as if your type was not ExpressibleByNilLiteral
and was an optional instead, so having a failable initializer doesn't
really make sense in that case (since you could've initialized `self` to
its own `nil` in case of failure). Still, some valid use cases may exist,
so the natural (and quite intuitive) way to circumvent this would be to
call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a
different thing in an initializer than it does in a function? Essentially,
then, you’re creating your own variation on an implicitly unwrapped
optional, where `self` is of type `inout Self?` for assignment in
initializers only but not for any other purpose. Implicitly unwrapped
optionals are hard to reason about, and having a variation on it would be
even harder to understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`;
however, I do think Greg is right that it would create more boilerplate
than the current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com> >>>>>>> wrote:

The type of `self` could remain `inout Self` inside the failable
initializer. The ability to assign nil would be a compiler magic (much like
`return nil` is compiler magic) that is meant to introduce uniformity to
the initialization logic.

The idea is to define all different ways initialization can take
place and expand them to be used uniformly on both `self` and all its
members, as well as remove the ways that do not make sense for their
purpose.

Currently, there are 3 ways of initializing self as a whole:
1. delegating initializer
2. assigning to self
3. returning nil

#1: The delegating initializer is pretty much perfect at this
point, in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside
failable initializers.

#3: The only thing that can be returned from an initializer is
`nil`, which is compiler magic, so we can thing of it as a misnomer
(because we aren't really **returning** anything).

If, for a second, we forget about potential factory initializers,
returning anything from an initializer doesn't make much sense, because an
initializer is conceptually meant to bring an existing object in memory to
a type-specific valid state. This semantic was very explicitly in
Objective-C with `[[MyType alloc] init]`. Especially since even
syntactically, the initializer does not specify any return type, the idea
of returning from an initializer is counter-intuitive both syntactically
and semantically.

The actual *behavior* of `return nil` is very sensible, so the
behavior, I imagine `self = nil`, would largely mean the same (except not
needed to return immediately and allowing non-self-accessing code to be
executed before return). Being able to assign `nil` to a non-optional
(ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to
initialize self to nil? That is what `self = nil` means if `self` is of
type `inout Self`. If `self` is of type `inout Self` and Self is not
ExpressibleByNilLiteral, then it must be an error to assign nil to self.
Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to

initialize an object in-place and doesn't look like it should return
anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init`
syntax could completely flip this logic, but making the initializer
essentially a static function that returns an object. In this case the
initializer could be made to specify the return type (that is the supertype
of all possible factory-created objects) and assigning to self would be
forbidden because there is not self yet:

extension MyProtocol {

public factory init(weCool: Bool) -> MyProtocol {
self = MyImpl() // error: cannot assign to `self` in a factory
initializer
self.init(...) // error: cannot make a delegating initializer call
in a factory initializer
if weCool {
return MyCoolImpl()
} else {
return MyUncoolImpl()
}
}

}

# In-place Member Initializers

In addition, member initialization currently is only possible with
#2 (as in `self.member = value`), which could be extended in a non-factory
initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while
giving a more reliable performance guarantee that this member will not be
copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

If `self` is not of type `inout Self?`, then what is the type of
`self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms
to `ExpressibleByNilLiteral`, in which case you are able to assign `self =
nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly
unwrapped optionals are no longer their own type, I’m not sure that’s
possible. But even if it were, that seems unintuitive and potentially
error-prone.

So I think Greg is quite right that, to enable this feature, `self`
would have to be of type `inout Self?`–which is intriguing but potentially
more boilerplatey than the status quo.
On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution < >>>>>>>> swift-evolution@swift.org> wrote:

Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized
and since `self` can only be initialized once, this would mean that after
`self = nil`, you won't be allowed to access `self` in your initializer at
all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason
to treat `self` as `inout Self?`, because the only place it can be `nil` is
the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution < >>>>>>>>> swift-evolution@swift.org> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable
initializers (essentially making `self` look like `inout Self?` instead of
`inout Self` with magical `return nil`), so that all initializers uniformly
can be written in `self = ...` form for clarity and convenience purposes.
This should, theoretically, be nothing but a `defer { return nil }` type of
rewrite, so I don't see any major difficulties implementing this. This is
especially useful for failable-initializing enums where the main switch
simply assigns to self in all cases and the rest of the initializer does
some post-processing.

I don't see how to avoid source incompatibility and uglification
of failable initializer implementations here. Allowing `self = nil` inside
a failable initializer would require `self` to be an optional. That in turn
would require every use of `self` in the initializer to be nil-checked or
forced. I don't think that loss everywhere outweighs the gain of `self =
nil` in some places.

--
Greg Parker gparker@apple.com Runtime Wrangler

_______________________________________________
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

_______________________________________________
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

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

There was another proposal that got rejected, which was about forcing the usage of `self.` on members.
I pretty much *require* it in my code for two reasons:
* The understandable requirement of `self.` in closures conflicts with the lack of `self.` in methods, which is confusing.
* The ability to refer to globals and members in the same way is also making the code harder to read.

The same goes for using `Self.` for associated types and type aliases inside protocols, because it's very easy to accidentally confuse them with global types, which would mess up the protocol.
I know that this adds a bit of code, but it does not make the code less readable (in the contrary) and modern IDEs are very capable of code completion, which negates the problem of having to type more text manually.

The argument agains this was something like "this is not worth sacrificing such a convenience".
On the other hand, on numerous occasions I've heard another argument against a proposal that said "it's not worth gaining terseness by sacrificing clarity".

This direct contradiction of priorities is worrying to me.

···

On Jun 11, 2017, at 11:21 AM, Adrian Zubarev <adrian.zubarev@devandartist.com> wrote:

Yeah, well I messed up my proposal from last year about removing the access modifier on extensions and wish now I wasn’t that confused back than and made it right.

The indirect keyword is literally the same story. The docs only says that this is only a shortcut.

„To enable indirection for all the cases of an enumeration, mark the entire enumeration with the indirect modifier—this is convenient when the enumeration contains many cases that would each need to be marked with the indirect modifier.“
If you really wish to reuse that keyword here we might need to remove such shortcuts from the language (indirect enum, access modifier on extensions, anything else?).

--
Adrian Zubarev
Sent with Airmail

Am 11. Juni 2017 um 10:12:38, Gor Gyolchanyan (gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>) schrieb:

I always wondered, why is `indirect` allowed on the `enum` itself? Wouldn't it make more sense to apply it to individual cases that recursively refer to the `enum`?
This question also applies to access modifiers on extensions. So, what is it supposed to do? Change the default access modifier from `internal` to whatever I specify? That's just confusing, reduces readability and the syntactic gain is marginal at best.
If the `indirect` confusion becomes real, I'd suggest getting rid of `indirect enum` and using `indirect case` instead.

On Jun 11, 2017, at 11:05 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

The proposal is looking good to me. :) It will also enable easy support for custom views using XIBs in iOS development without unnecessary view nesting.

For instance the function from this example ios - Loading a XIB file to a UIView Swift - Stack Overflow could be used directly inside an init:

class MyView : UIView {
      
      indirect init() {
            return MyView.instantiateFromXib()
            // Or after SR-0068
            return Self.instantiateFromXib()
      }
}
There is still one little thing that bothers me, it might be a little bit confusing to have two different meanings of indirect on enums.

indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)
      
    // This might makes no sense, but it would still be possible after
    // this proposal.
    indirect init(other: ArithmeticExpression) {
       return other
    }
      
    // Furthermore if the keyboard is applied to the enum
    // directly all other `indirect` uses are inferred.
    // Will this be implicitly `indirect` because of the previous fact?
    init() { … }
}

--
Adrian Zubarev
Sent with Airmail

Am 11. Juni 2017 um 00:38:56, Riley Testut via swift-evolution (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) schrieb:

Awesome! Updated my proposal to include what I believed to be the relevant portions of your indirect initializer idea. Let me know if there’s anything I missed or should change :-)

https://github.com/rileytestut/swift-evolution/blob/master/proposals/NNNN-factory-initializers.md

On Jun 10, 2017, at 12:43 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:

Hi, Riley!

I think that's a great idea! We can merge the second part of my proposal (the `indirect init`) into your one and refine and consolidate the prerequisite proposal (about returning from `init` and possibly in-place member initializers) and bunch them up into a proposal cluster (the way swift coders did).
Feel free to tear out any chunks from my proposal, while I think about a more in-depth rationale about revamping initialization syntax. :slightly_smiling_face:

On Jun 10, 2017, at 8:36 PM, Riley Testut <rileytestut@gmail.com <mailto:rileytestut@gmail.com>> wrote:

Hi Gor :wave:

I’m very much in fan of a unified initialization syntax. I submitted my own proposal for factory initializers a while back, but since it wasn’t a focus of Swift 3 or 4 I haven’t followed up on it recently. In the time since last working on it, I came to my own conclusion that rather than focusing on factory initialization, the overall initialization process should be simplified, which I’m glad to see someone else has realized as well :-)

Here’s my proposal for reference: Proposal: Factory Initializers by rileytestut · Pull Request #247 · apple/swift-evolution · GitHub Originally I used the “factory” keyword, but I think your “indirect” keyword may be a better fit (since it has precedent in the language and is not limited to “just” being about factory initialization). To divide your proposal up into smaller pieces for review, maybe we could update my proposal to use your indirect keyword, and then start a separate topic/proposal for the remaining aspects of your proposal? I agree that splitting it into smaller chunks may be better for the process.

Let me know what you think!

Riley

On Jun 10, 2017, at 3:33 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This is a very interesting read.

Thanks you! I tried to make it as clear and detailed as possible. :slightly_smiling_face:

We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

I was writing the proposal and was just about to write `factory init`, when it occurred to me: enums already have a keyword that does something very similar. It seemed to me that an initializer that doesn't initialize the instance in-place, but returns a completely separate instance from somewhere else, is kinda "indirectly" initializing the instance. Plus, the already established keyword and its semantic would reduce the learning curve for this new feature and separate it from a single specific use case (the "factory method" pattern).

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

I think the `return` can be easily implemented first, while opening up an opportunity to later implement `indirect init`. The reason why I unified them was that the `return` idea on its own has very limited merit and could the thought of as a low-priority cosmetic enhancement. I wouldn't want it to be viewed that way because the primary purpose of that idea is to enable `indirect init` (which Cocoa and Cocoa Touch developers would be very happy about).

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

Very good point. The challenge is to correctly separate them, without losing context in their respective proposals and without bleeding the proposals into each other.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

I'd never send a pull request to swift-evolution without thoroughly discussing it here. I just though, if I'm going to write a whole proposal with examples and motivation, it would be easier to demonstrate it and discuss in with the community If I just went ahead and wrote the whole thing and sent the link. This way it would be clearer to the reader and the discussed changes would be accurately reflected by the commits I'd make to my proposal.

Original Message

On Jun 10, 2017, at 2:38 AM, Daryle Walker via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/master/proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed it wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

This is a very interesting read. We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Cool. I have reservations about idea #3, but we can tackle that another day. (Real life things beckon.) But suffice it to say that I now really, really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self` non-optional.
This would make `return nil` less out-of-place, like you said, while still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax, while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it to change the signature as well as remove any compiler assumptions about the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
So far, we've discussed two ways of interpreting `self = nil`, both of which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as counter-intuitive, but recall that `return nil` is just as much of a special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax because the initializer notionally has no return value. Personally, I have always disliked `return nil` in failable initializers for that reason, but I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because, in the case of a failable initializer, `return nil` continues to have the same meaning if we consider the return value of the initializer to be of type `Self?`. For that reason, I think your idea #2 is quite clever, and it would go a long way in making `return nil` a lot less odd. It also increases the expressivity of initializers because it allows one to set the value of self and also return in one statement, clearly demonstrating the intention that no other code in the initializer should be run before returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with initialization semantics, it provides more uniform syntax and it's a bit less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more cumbersome. Implicitly unwrapped optionals are a bit difficult, but this "variation" of it is much more restrictive then the normal ones, because unlike normal implicitly unwrapped optionals, this one cannot be accessed after being assigned nil (and it also cannot be indirectly assigned `nil`, because escaping `self` is not allowed before full initialization), so there is only one possible place it can be set to nil and that's directly in the initializer. This means that `self` can be safely treated as `inout Self` before being set to nil (and after being set to nil, it doesn't matter any more because you aren't allowed to access it, due to not being fully initialized).

I have to say, I don’t like either of these explanations at all. I think having a “special” IUO is a difficult sell; it is just conceptually too complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language wonkier because it currently has a parallel wonky feature in `return nil` seems like the wrong way to go. In addition, there’s nothing gained here that cannot be done with a defer statement; of course, defer statements might not be very elegant, but it would certainly be less wonky than inventing a new variation on an IUO to allow assignment of nil to self... For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic and the restrictions of `self as inout Self!` are imposed by already existing and well-understood initialization logic, so the provided guarantees don't really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
I think a good approach would be to have `self = nil` only mean `the initializer is going to fail` because if your type is ExpressibleByNilLiteral, it means that the `nil` of your type already carries the same meaning as if your type was not ExpressibleByNilLiteral and was an optional instead, so having a failable initializer doesn't really make sense in that case (since you could've initialized `self` to its own `nil` in case of failure). Still, some valid use cases may exist, so the natural (and quite intuitive) way to circumvent this would be to call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different thing in an initializer than it does in a function? Essentially, then, you’re creating your own variation on an implicitly unwrapped optional, where `self` is of type `inout Self?` for assignment in initializers only but not for any other purpose. Implicitly unwrapped optionals are hard to reason about, and having a variation on it would be even harder to understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however, I do think Greg is right that it would create more boilerplate than the current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
The type of `self` could remain `inout Self` inside the failable initializer. The ability to assign nil would be a compiler magic (much like `return nil` is compiler magic) that is meant to introduce uniformity to the initialization logic.

The idea is to define all different ways initialization can take place and expand them to be used uniformly on both `self` and all its members, as well as remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
1. delegating initializer
2. assigning to self
3. returning nil

#1: The delegating initializer is pretty much perfect at this point, in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside failable initializers.

#3: The only thing that can be returned from an initializer is `nil`, which is compiler magic, so we can thing of it as a misnomer (because we aren't really **returning** anything).

If, for a second, we forget about potential factory initializers, returning anything from an initializer doesn't make much sense, because an initializer is conceptually meant to bring an existing object in memory to a type-specific valid state. This semantic was very explicitly in Objective-C with `[[MyType alloc] init]`. Especially since even syntactically, the initializer does not specify any return type, the idea of returning from an initializer is counter-intuitive both syntactically and semantically.

The actual *behavior* of `return nil` is very sensible, so the behavior, I imagine `self = nil`, would largely mean the same (except not needed to return immediately and allowing non-self-accessing code to be executed before return). Being able to assign `nil` to a non-optional (ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to initialize self to nil? That is what `self = nil` means if `self` is of type `inout Self`. If `self` is of type `inout Self` and Self is not ExpressibleByNilLiteral, then it must be an error to assign nil to self. Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to initialize an object in-place and doesn't look like it should return anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init` syntax could completely flip this logic, but making the initializer essentially a static function that returns an object. In this case the initializer could be made to specify the return type (that is the supertype of all possible factory-created objects) and assigning to self would be forbidden because there is not self yet:

extension MyProtocol {

public factory init(weCool: Bool) -> MyProtocol {
self = MyImpl() // error: cannot assign to `self` in a factory initializer
self.init(...) // error: cannot make a delegating initializer call in a factory initializer
if weCool {
return MyCoolImpl()
} else {
return MyUncoolImpl()
}
}

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2 (as in `self.member = value`), which could be extended in a non-factory initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while giving a more reliable performance guarantee that this member will not be copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

If `self` is not of type `inout Self?`, then what is the type of `self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms to `ExpressibleByNilLiteral`, in which case you are able to assign `self = nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped optionals are no longer their own type, I’m not sure that’s possible. But even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self` would have to be of type `inout Self?`–which is intriguing but potentially more boilerplatey than the status quo.
On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and since `self` can only be initialized once, this would mean that after `self = nil`, you won't be allowed to access `self` in your initializer at all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to treat `self` as `inout Self?`, because the only place it can be `nil` is the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com <mailto:gparker@apple.com>> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable initializers (essentially making `self` look like `inout Self?` instead of `inout Self` with magical `return nil`), so that all initializers uniformly can be written in `self = ...` form for clarity and convenience purposes. This should, theoretically, be nothing but a `defer { return nil }` type of rewrite, so I don't see any major difficulties implementing this. This is especially useful for failable-initializing enums where the main switch simply assigns to self in all cases and the rest of the initializer does some post-processing.

I don't see how to avoid source incompatibility and uglification of failable initializer implementations here. Allowing `self = nil` inside a failable initializer would require `self` to be an optional. That in turn would require every use of `self` in the initializer to be nil-checked or forced. I don't think that loss everywhere outweighs the gain of `self = nil` in some places.

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler

_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

Removal of access modifiers on extensions has been proposed, reviewed, and
rejected, so that’s that.

In general, Swift uses distinct keywords for distinct concepts, unlike Rust
which likes to reuse keywords in clever ways; if you’re finding that things
are getting confusing with one word meaning two things, that shouldn’t be
an invitation to rip out existing syntax but is probably a good sign you
shouldn’t be repurposing that keyword.

···

On Sun, Jun 11, 2017 at 03:28 Adrian Zubarev via swift-evolution < swift-evolution@swift.org> wrote:

Yeah, well I messed up my proposal from last year about removing the
access modifier on extensions and wish now I wasn’t that confused back than
and made it right.

The indirect keyword is literally the same story. The docs only says that
this is only a shortcut.

„To enable indirection for all the cases of an enumeration, mark the
entire enumeration with the indirect modifier—this is convenient when the
enumeration contains many cases that would each need to be marked with the
indirect modifier.“

If you really wish to reuse that keyword here we might need to remove such
shortcuts from the language (indirect enum, access modifier on extensions,
anything else?).

--
Adrian Zubarev
Sent with Airmail

Am 11. Juni 2017 um 10:12:38, Gor Gyolchanyan (gor@gyolchanyan.com)
schrieb:

I always wondered, why is `indirect` allowed on the `enum` itself?
Wouldn't it make more sense to apply it to individual cases that
recursively refer to the `enum`?
This question also applies to access modifiers on extensions. So, what is
it supposed to do? Change the default access modifier from `internal` to
whatever I specify? That's just confusing, reduces readability and the
syntactic gain is marginal at best.
If the `indirect` confusion becomes real, I'd suggest getting rid of
`indirect enum` and using `indirect case` instead.

On Jun 11, 2017, at 11:05 AM, Adrian Zubarev via swift-evolution < > swift-evolution@swift.org> wrote:

The proposal is looking good to me. :) It will also enable easy support
for custom views using XIBs in iOS development without unnecessary view
nesting.

For instance the function from this example
ios - Loading a XIB file to a UIView Swift - Stack Overflow could be used directly
inside an init:

class MyView : UIView {

      indirect init() {
            return MyView.instantiateFromXib()
            // Or after SR-0068
            return Self.instantiateFromXib()
      }
}

There is still one little thing that bothers me, it might be a little bit
confusing to have two different meanings of indirect on enums.

indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)

    // This might makes no sense, but it would still be possible after
    // this proposal.
    indirect init(other: ArithmeticExpression) {
       return other
    }

    // Furthermore if the keyboard is applied to the enum
    // directly all other `indirect` uses are inferred.
    // Will this be implicitly `indirect` because of the previous fact?
    init() { … }
}

--
Adrian Zubarev
Sent with Airmail

Am 11. Juni 2017 um 00:38:56, Riley Testut via swift-evolution (
swift-evolution@swift.org) schrieb:

Awesome! Updated my proposal to include what I believed to be the relevant
portions of your indirect initializer idea. Let me know if there’s anything
I missed or should change :-)

https://github.com/rileytestut/swift-evolution/blob/master/proposals/NNNN-factory-initializers.md

On Jun 10, 2017, at 12:43 PM, Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

Hi, Riley!

I think that's a great idea! We can merge the second part of my proposal
(the `indirect init`) into your one and refine and consolidate the
prerequisite proposal (about returning from `init` and possibly in-place
member initializers) and bunch them up into a proposal cluster (the way
swift coders did).
Feel free to tear out any chunks from my proposal, while I think about a
more in-depth rationale about revamping initialization syntax. :slightly_smiling_face:

On Jun 10, 2017, at 8:36 PM, Riley Testut <rileytestut@gmail.com> wrote:

Hi Gor :wave:

I’m very much in fan of a unified initialization syntax. I submitted my
own proposal for factory initializers a while back, but since it wasn’t a
focus of Swift 3 or 4 I haven’t followed up on it recently. In the time
since last working on it, I came to my own conclusion that rather than
focusing on factory initialization, the overall initialization process
should be simplified, which I’m glad to see someone else has realized as
well :-)

Here’s my proposal for reference:
Proposal: Factory Initializers by rileytestut · Pull Request #247 · apple/swift-evolution · GitHub
Originally I used the “factory” keyword, but I think your “indirect”
keyword may be a better fit (since it has precedent in the language and is
not limited to “just” being about factory initialization). To divide your
proposal up into smaller pieces for review, maybe we could update my
proposal to use your indirect keyword, and then start a separate
topic/proposal for the remaining aspects of your proposal? I agree that
splitting it into smaller chunks may be better for the process.

Let me know what you think!

Riley

On Jun 10, 2017, at 3:33 AM, Gor Gyolchanyan via swift-evolution < > swift-evolution@swift.org> wrote:

This is a very interesting read.

Thanks you! I tried to make it as clear and detailed as possible. :slightly_smiling_face:

We did not discuss the 'indirect' idea at all on this list. Did you come
up with it just now? In any case, my suggestion as to moving forward would
be this:

I was writing the proposal and was just about to write `factory init`,
when it occurred to me: enums already have a keyword that does something
very similar. It seemed to me that an initializer that doesn't initialize
the instance in-place, but returns a completely separate instance from
somewhere else, is kinda "indirectly" initializing the instance. Plus, the
already established keyword and its semantic would reduce the learning
curve for this new feature and separate it from a single specific use case
(the "factory method" pattern).

- Do you feel that both halves of your draft (expanding `return` in
initializers, and `indirect` initializers) should absolutely be one
proposal, or can they be separated?

I think the `return` can be easily implemented first, while opening up an
opportunity to later implement `indirect init`. The reason why I unified
them was that the `return` idea on its own has very limited merit and could
the thought of as a low-priority cosmetic enhancement. I wouldn't want it
to be viewed that way because the primary purpose of that idea is to enable
`indirect init` (which Cocoa and Cocoa Touch developers would be very happy
about).

a) If they can be separated because each half has individual merit, then
these ideas may be more likely to succeed as separate proposals, as each
can be critiqued fully and judged independently as digestible units.

Very good point. The challenge is to correctly separate them, without
losing context in their respective proposals and without bleeding the
proposals into each other.

b) If you intend to tackle all your ideas all at once, that's going to be
a much bigger change--in terms of review effort, likely bikeshedding, and
implementation effort. It'll probably be best to solicit initial feedback
on this list first about `indirect` initializers, even if just to
familiarize the community with the idea, before launching into a pitch of
the whole proposal.

I'd never send a pull request to swift-evolution without thoroughly
discussing it here. I just though, if I'm going to write a whole proposal
with examples and motivation, it would be easier to demonstrate it and
discuss in with the community If I just went ahead and wrote the whole
thing and sent the link. This way it would be clearer to the reader and the
discussed changes would be accurately reflected by the commits I'd make to
my proposal.

Original Message

On Jun 10, 2017, at 2:38 AM, Daryle Walker via swift-evolution < > swift-evolution@swift.org> wrote:

On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <gor@gyolchanyan.com> > wrote:

Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/master/proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed
it wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

This is a very interesting read. We did not discuss the 'indirect' idea at
all on this list. Did you come up with it just now? In any case, my
suggestion as to moving forward would be this:

- Do you feel that both halves of your draft (expanding `return` in
initializers, and `indirect` initializers) should absolutely be one
proposal, or can they be separated?

a) If they can be separated because each half has individual merit, then
these ideas may be more likely to succeed as separate proposals, as each
can be critiqued fully and judged independently as digestible units.

b) If you intend to tackle all your ideas all at once, that's going to be
a much bigger change--in terms of review effort, likely bikeshedding, and
implementation effort. It'll probably be best to solicit initial feedback
on this list first about `indirect` initializers, even if just to
familiarize the community with the idea, before launching into a pitch of
the whole proposal.

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Cool. I have reservations about idea #3, but we can tackle that another
day. (Real life things beckon.) But suffice it to say that I now really,
really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com> wrote:

You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the
signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are
non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self`
non-optional.
This would make `return nil` less out-of-place, like you said, while
still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax,
while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it
to change the signature as well as remove any compiler assumptions about
the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place
initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com> >>> wrote:

So far, we've discussed two ways of interpreting `self = nil`, both of
which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as
counter-intuitive, but recall that `return nil` is just as much of a
special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax
because the initializer notionally has no return value. Personally, I have
always disliked `return nil` in failable initializers for that reason, but
I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because,
in the case of a failable initializer, `return nil` continues to have the
same meaning if we consider the return value of the initializer to be of
type `Self?`. For that reason, I think your idea #2 is quite clever, and it
would go a long way in making `return nil` a lot less odd. It also
increases the expressivity of initializers because it allows one to set the
value of self and also return in one statement, clearly demonstrating the
intention that no other code in the initializer should be run before
returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with

initialization semantics, it provides more uniform syntax and it's a bit
less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more
cumbersome. Implicitly unwrapped optionals are a bit difficult, but this
"variation" of it is much more restrictive then the normal ones, because
unlike normal implicitly unwrapped optionals, this one cannot be accessed
after being assigned nil (and it also cannot be indirectly assigned `nil`,
because escaping `self` is not allowed before full initialization), so
there is only one possible place it can be set to nil and that's directly
in the initializer. This means that `self` can be safely treated as `inout
Self` before being set to nil (and after being set to nil, it doesn't
matter any more because you aren't allowed to access it, due to not being
fully initialized).

I have to say, I don’t like either of these explanations at all. I think
having a “special” IUO is a difficult sell; it is just conceptually too
complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language
wonkier because it currently has a parallel wonky feature in `return nil`
seems like the wrong way to go. In addition, there’s nothing gained here
that cannot be done with a defer statement; of course, defer statements
might not be very elegant, but it would certainly be less wonky than
inventing a new variation on an IUO to allow assignment of nil to self...
For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic

and the restrictions of `self as inout Self!` are imposed by already
existing and well-understood initialization logic, so the provided
guarantees don't really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com> >>>> wrote:

I think a good approach would be to have `self = nil` only mean `the
initializer is going to fail` because if your type is
ExpressibleByNilLiteral, it means that the `nil` of your type already
carries the same meaning as if your type was not ExpressibleByNilLiteral
and was an optional instead, so having a failable initializer doesn't
really make sense in that case (since you could've initialized `self` to
its own `nil` in case of failure). Still, some valid use cases may exist,
so the natural (and quite intuitive) way to circumvent this would be to
call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different
thing in an initializer than it does in a function? Essentially, then,
you’re creating your own variation on an implicitly unwrapped optional,
where `self` is of type `inout Self?` for assignment in initializers only
but not for any other purpose. Implicitly unwrapped optionals are hard to
reason about, and having a variation on it would be even harder to
understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however,
I do think Greg is right that it would create more boilerplate than the
current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com> >>>>> wrote:

The type of `self` could remain `inout Self` inside the failable
initializer. The ability to assign nil would be a compiler magic (much like
`return nil` is compiler magic) that is meant to introduce uniformity to
the initialization logic.

The idea is to define all different ways initialization can take
place and expand them to be used uniformly on both `self` and all its
members, as well as remove the ways that do not make sense for their
purpose.

Currently, there are 3 ways of initializing self as a whole:
1. delegating initializer
2. assigning to self
3. returning nil

#1: The delegating initializer is pretty much perfect at this point,
in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside
failable initializers.

#3: The only thing that can be returned from an initializer is
`nil`, which is compiler magic, so we can thing of it as a misnomer
(because we aren't really **returning** anything).

If, for a second, we forget about potential factory initializers,
returning anything from an initializer doesn't make much sense, because an
initializer is conceptually meant to bring an existing object in memory to
a type-specific valid state. This semantic was very explicitly in
Objective-C with `[[MyType alloc] init]`. Especially since even
syntactically, the initializer does not specify any return type, the idea
of returning from an initializer is counter-intuitive both syntactically
and semantically.

The actual *behavior* of `return nil` is very sensible, so the
behavior, I imagine `self = nil`, would largely mean the same (except not
needed to return immediately and allowing non-self-accessing code to be
executed before return). Being able to assign `nil` to a non-optional
(ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to
initialize self to nil? That is what `self = nil` means if `self` is of
type `inout Self`. If `self` is of type `inout Self` and Self is not
ExpressibleByNilLiteral, then it must be an error to assign nil to self.
Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to

initialize an object in-place and doesn't look like it should return
anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init`
syntax could completely flip this logic, but making the initializer
essentially a static function that returns an object. In this case the
initializer could be made to specify the return type (that is the supertype
of all possible factory-created objects) and assigning to self would be
forbidden because there is not self yet:

extension MyProtocol {

public factory init(weCool: Bool) -> MyProtocol {
self = MyImpl() // error: cannot assign to `self` in a factory
initializer
self.init(...) // error: cannot make a delegating initializer call in
a factory initializer
if weCool {
return MyCoolImpl()
} else {
return MyUncoolImpl()
}
}

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2
(as in `self.member = value`), which could be extended in a non-factory
initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while
giving a more reliable performance guarantee that this member will not be
copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

If `self` is not of type `inout Self?`, then what is the type of
`self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms
to `ExpressibleByNilLiteral`, in which case you are able to assign `self =
nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped
optionals are no longer their own type, I’m not sure that’s possible. But
even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self`
would have to be of type `inout Self?`–which is intriguing but potentially
more boilerplatey than the status quo.
On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution < >>>>>> swift-evolution@swift.org> wrote:

Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and
since `self` can only be initialized once, this would mean that after `self
= nil`, you won't be allowed to access `self` in your initializer at
all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to
treat `self` as `inout Self?`, because the only place it can be `nil` is
the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution < >>>>>>> swift-evolution@swift.org> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable
initializers (essentially making `self` look like `inout Self?` instead of
`inout Self` with magical `return nil`), so that all initializers uniformly
can be written in `self = ...` form for clarity and convenience purposes.
This should, theoretically, be nothing but a `defer { return nil }` type of
rewrite, so I don't see any major difficulties implementing this. This is
especially useful for failable-initializing enums where the main switch
simply assigns to self in all cases and the rest of the initializer does
some post-processing.

I don't see how to avoid source incompatibility and uglification of
failable initializer implementations here. Allowing `self = nil` inside a
failable initializer would require `self` to be an optional. That in turn
would require every use of `self` in the initializer to be nil-checked or
forced. I don't think that loss everywhere outweighs the gain of `self =
nil` in some places.

--
Greg Parker gparker@apple.com Runtime Wrangler

_______________________________________________
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

_______________________________________________
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

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

I have no better name besides a factory initializer for now.
I have thought about this some more and came to this conclusion about the keyword:
Let the keyword be universally applied to all factory initializers, to statically enforce the rules of factory initializers (see below), because the more I think of it, the more I realize that you'd generally not want to mix factory and non-factory initializers, due to their vastly differing purposes.

Having said that, my current understanding of this proposal is as follows:

* Allow marking initializers inside protocol extensions, class declarations and class extensions as `factory`.
* In initializers marked as `factory`:
  * Change the implicit `self` parameter to mean `the dynamic type of the enclosing type` (just like it does in static methods).
  * Disallow delegating initialization to initializers not marked as `factory`.
  * Require terminating the initializer by either returning a compatible type (a conforming type for protocols, a derived instance for classes) or returning `nil` (if the initializer is failable).
* In initializers inside enum declarations, enum extensions, struct declarations and struct extensions:
  * Allow terminating the initializer by returning an instance of the type being initialized.

···

On Jun 11, 2017, at 7:38 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Sun, Jun 11, 2017 at 10:34 AM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
I just didn't want to use the commonly proposed `factory` word, because it implies a specific semantic tied to the factory method pattern.
I gave it another thought and I'm thinking maybe we can forego the annotation and have the compiler deduce it automatically.
There are only two places where an indirect initializer can exist:
* Protocol extensions, returning a conforming type.
* Classes, returning an instance.
It doesn't make sense to have this on value types, since they do not have subtypes of any kind.
Indirect initializers are very unambiguous in protocol extensions, because the only other way of implementing an initializer in a protocol extension is via delegating initialization, so the indirect-ness of the initializer can be statically determined by whether or not there is a delegating initializer involved.
If the initializer in a protocol extension has a delegating initialization on any execution path, then returning an instance is disallowed and vice versa. This will ensure strict separation of initializer types for the compiler to generate code for.
If a failable initializer in a protocol extension unconditionally returns `nil`, then no initialization takes place anyway, so it doesn't matter, which one the compiler chooses.
In classes this is a bit difficult, because besides delegating initializers, they also can initialize the members directly.
So, in addition to the distinguishing rule for the protocol extensions, classes will also check whether any member is assigned to on any execution path.

What do you think?

Keywords aren't just for the compiler; they're for the human reader too! If you believe the use of your proposed feature in protocol extensions is unambiguous to humans as well as compilers, then IMO it makes sense not to require another keyword in that place. I haven't thought deeply about whether that would be the case.

Clearly, you're saying that this is a more complicated situation with classes; I think it makes sense for you to consider requiring a keyword there. There is precedent for keywords modifying `init` to be required for classes but not for value types (e.g., `convenience`).

Regardless of whether a keyword is required or not, your feature needs a name. And here again, I think it is puzzling that you are calling them "indirect initializers" when there is already another meaning for "indirect" in Swift. Distinct concepts should have distinct names.

On Jun 11, 2017, at 5:53 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Sun, Jun 11, 2017 at 8:49 AM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
Can you recall the reasons why the removal of access modifiers on extensions was rejected?

It was an unassailable reason, really: people found this shorthand useful and wanted to continue to use it--it is the only way to specify that multiple members are public without explicitly labeling each one. The core team agreed it was useful.

My takeaway from the whole episode (I was greatly in favor of removing this shorthand, as it's highly inconsistent with all other access modifier rules) is that in general, since the bar for new syntax is so high, if a shorthand made it into the language (and especially if it's kind of an inconsistent shorthand) the general presumption must be that it is highly desired.

Also, do you think `indirect init` is confusing inside an `indirect enum`?

I do. These are unrelated definitions of "indirect," and I'm puzzled why you'd actively choose to run into issues with the same word meaning two things when you could choose another word.

On Jun 11, 2017, at 4:40 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Removal of access modifiers on extensions has been proposed, reviewed, and rejected, so that’s that.

In general, Swift uses distinct keywords for distinct concepts, unlike Rust which likes to reuse keywords in clever ways; if you’re finding that things are getting confusing with one word meaning two things, that shouldn’t be an invitation to rip out existing syntax but is probably a good sign you shouldn’t be repurposing that keyword.

On Sun, Jun 11, 2017 at 03:28 Adrian Zubarev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Yeah, well I messed up my proposal from last year about removing the access modifier on extensions and wish now I wasn’t that confused back than and made it right.

The indirect keyword is literally the same story. The docs only says that this is only a shortcut.

„To enable indirection for all the cases of an enumeration, mark the entire enumeration with the indirect modifier—this is convenient when the enumeration contains many cases that would each need to be marked with the indirect modifier.“

If you really wish to reuse that keyword here we might need to remove such shortcuts from the language (indirect enum, access modifier on extensions, anything else?).

--
Adrian Zubarev
Sent with Airmail

Am 11. Juni 2017 um 10:12:38, Gor Gyolchanyan (gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>) schrieb:

I always wondered, why is `indirect` allowed on the `enum` itself? Wouldn't it make more sense to apply it to individual cases that recursively refer to the `enum`?
This question also applies to access modifiers on extensions. So, what is it supposed to do? Change the default access modifier from `internal` to whatever I specify? That's just confusing, reduces readability and the syntactic gain is marginal at best.
If the `indirect` confusion becomes real, I'd suggest getting rid of `indirect enum` and using `indirect case` instead.

On Jun 11, 2017, at 11:05 AM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

The proposal is looking good to me. :) It will also enable easy support for custom views using XIBs in iOS development without unnecessary view nesting.

For instance the function from this example ios - Loading a XIB file to a UIView Swift - Stack Overflow could be used directly inside an init:

class MyView : UIView {
      
      indirect init() {
            return MyView.instantiateFromXib()
            // Or after SR-0068
            return Self.instantiateFromXib()
      }
}
There is still one little thing that bothers me, it might be a little bit confusing to have two different meanings of indirect on enums.

indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)
      
    // This might makes no sense, but it would still be possible after
    // this proposal.
    indirect init(other: ArithmeticExpression) {
       return other
    }
      
    // Furthermore if the keyboard is applied to the enum
    // directly all other `indirect` uses are inferred.
    // Will this be implicitly `indirect` because of the previous fact?
    init() { … }
}

--
Adrian Zubarev
Sent with Airmail

Am 11. Juni 2017 um 00:38:56, Riley Testut via swift-evolution (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) schrieb:

Awesome! Updated my proposal to include what I believed to be the relevant portions of your indirect initializer idea. Let me know if there’s anything I missed or should change :-)

https://github.com/rileytestut/swift-evolution/blob/master/proposals/NNNN-factory-initializers.md

On Jun 10, 2017, at 12:43 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:

Hi, Riley!

I think that's a great idea! We can merge the second part of my proposal (the `indirect init`) into your one and refine and consolidate the prerequisite proposal (about returning from `init` and possibly in-place member initializers) and bunch them up into a proposal cluster (the way swift coders did).
Feel free to tear out any chunks from my proposal, while I think about a more in-depth rationale about revamping initialization syntax. :slightly_smiling_face:

On Jun 10, 2017, at 8:36 PM, Riley Testut <rileytestut@gmail.com <mailto:rileytestut@gmail.com>> wrote:

Hi Gor :wave:

I’m very much in fan of a unified initialization syntax. I submitted my own proposal for factory initializers a while back, but since it wasn’t a focus of Swift 3 or 4 I haven’t followed up on it recently. In the time since last working on it, I came to my own conclusion that rather than focusing on factory initialization, the overall initialization process should be simplified, which I’m glad to see someone else has realized as well :-)

Here’s my proposal for reference: Proposal: Factory Initializers by rileytestut · Pull Request #247 · apple/swift-evolution · GitHub Originally I used the “factory” keyword, but I think your “indirect” keyword may be a better fit (since it has precedent in the language and is not limited to “just” being about factory initialization). To divide your proposal up into smaller pieces for review, maybe we could update my proposal to use your indirect keyword, and then start a separate topic/proposal for the remaining aspects of your proposal? I agree that splitting it into smaller chunks may be better for the process.

Let me know what you think!

Riley

On Jun 10, 2017, at 3:33 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

This is a very interesting read.

Thanks you! I tried to make it as clear and detailed as possible. :slightly_smiling_face:

We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

I was writing the proposal and was just about to write `factory init`, when it occurred to me: enums already have a keyword that does something very similar. It seemed to me that an initializer that doesn't initialize the instance in-place, but returns a completely separate instance from somewhere else, is kinda "indirectly" initializing the instance. Plus, the already established keyword and its semantic would reduce the learning curve for this new feature and separate it from a single specific use case (the "factory method" pattern).

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

I think the `return` can be easily implemented first, while opening up an opportunity to later implement `indirect init`. The reason why I unified them was that the `return` idea on its own has very limited merit and could the thought of as a low-priority cosmetic enhancement. I wouldn't want it to be viewed that way because the primary purpose of that idea is to enable `indirect init` (which Cocoa and Cocoa Touch developers would be very happy about).

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

Very good point. The challenge is to correctly separate them, without losing context in their respective proposals and without bleeding the proposals into each other.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

I'd never send a pull request to swift-evolution without thoroughly discussing it here. I just though, if I'm going to write a whole proposal with examples and motivation, it would be easier to demonstrate it and discuss in with the community If I just went ahead and wrote the whole thing and sent the link. This way it would be clearer to the reader and the discussed changes would be accurately reflected by the commits I'd make to my proposal.

Original Message

On Jun 10, 2017, at 2:38 AM, Daryle Walker via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Fri, Jun 9, 2017 at 5:32 PM, Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
Forked swift-evolution, created a draft proposal:

https://github.com/technogen-gg/swift-evolution/blob/master/proposals/NNNN-uniform-initialization.md

This is my first proposal, so I might have missed something or composed it wrong, so please feel free to comment, fork and send pull requests. :slightly_smiling_face:

This is a very interesting read. We did not discuss the 'indirect' idea at all on this list. Did you come up with it just now? In any case, my suggestion as to moving forward would be this:

- Do you feel that both halves of your draft (expanding `return` in initializers, and `indirect` initializers) should absolutely be one proposal, or can they be separated?

a) If they can be separated because each half has individual merit, then these ideas may be more likely to succeed as separate proposals, as each can be critiqued fully and judged independently as digestible units.

b) If you intend to tackle all your ideas all at once, that's going to be a much bigger change--in terms of review effort, likely bikeshedding, and implementation effort. It'll probably be best to solicit initial feedback on this list first about `indirect` initializers, even if just to familiarize the community with the idea, before launching into a pitch of the whole proposal.

On Jun 9, 2017, at 3:24 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Cool. I have reservations about idea #3, but we can tackle that another day. (Real life things beckon.) But suffice it to say that I now really, really like your idea #2.
On Fri, Jun 9, 2017 at 08:06 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
You know, come to think of it, I totally agree, and here's why:
A normal initializer (if #2 is accepted) would *conceptually* have the signature:

mutating func `init`(...) -> Self

Which would mean that both `self` and the returned result are non-optional.
A failable initializer could then have the signature:

mutating func `init`() -> Self?

Which would make the returned result optional, but leave `self` non-optional.
This would make `return nil` less out-of-place, like you said, while still leaving `self` as a set-exactly-once `inout Self`.
A factory initializer would then have the signature:

static func `init`(...) -> Self

or in case of a failable factory initializer:

static func `init`(...) -> Self?

Which would still make sense with the now legal `return ...` syntax, while adding the restriction of not having any `self` at all.
So, annotating the initializer with the keyword `factory` would cause it to change the signature as well as remove any compiler assumptions about the dynamic type of the returned instance.

In addition, idea #3 would be available for more deterministic in-place initialization.

On Jun 9, 2017, at 2:47 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:33 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
So far, we've discussed two ways of interpreting `self = nil`, both of which have a sensible solution, in my opinion:

1. It's a special rule like you said, which can be seen as counter-intuitive, but recall that `return nil` is just as much of a special rule and is also largely counter-intuitive.

`return nil` is “special,” but it doesn’t conflict with any other syntax because the initializer notionally has no return value. Personally, I have always disliked `return nil` in failable initializers for that reason, but I couldn’t come up with a better alternative.

Your proposed idea to allow returning any value is interesting because, in the case of a failable initializer, `return nil` continues to have the same meaning if we consider the return value of the initializer to be of type `Self?`. For that reason, I think your idea #2 is quite clever, and it would go a long way in making `return nil` a lot less odd. It also increases the expressivity of initializers because it allows one to set the value of self and also return in one statement, clearly demonstrating the intention that no other code in the initializer should be run before returning.

For all of those reasons, I think idea #2 is a winning idea.

The benefit of `self = nil` is that it's much more in line with initialization semantics, it provides more uniform syntax and it's a bit less restrictive.

2. It's an `inout Self!`, like Greg said, which can be seen as more cumbersome. Implicitly unwrapped optionals are a bit difficult, but this "variation" of it is much more restrictive then the normal ones, because unlike normal implicitly unwrapped optionals, this one cannot be accessed after being assigned nil (and it also cannot be indirectly assigned `nil`, because escaping `self` is not allowed before full initialization), so there is only one possible place it can be set to nil and that's directly in the initializer. This means that `self` can be safely treated as `inout Self` before being set to nil (and after being set to nil, it doesn't matter any more because you aren't allowed to access it, due to not being fully initialized).

I have to say, I don’t like either of these explanations at all. I think having a “special” IUO is a difficult sell; it is just conceptually too complicated, and I don’t agree that it gains you much.

By your own admission, `self = nil` is wonky, and making the language wonkier because it currently has a parallel wonky feature in `return nil` seems like the wrong way to go. In addition, there’s nothing gained here that cannot be done with a defer statement; of course, defer statements might not be very elegant, but it would certainly be less wonky than inventing a new variation on an IUO to allow assignment of nil to self... For those reasons, I conclude that I’m not excited about your idea #1.

Overall, I'd go with #2 because it involves much less confusing magic and the restrictions of `self as inout Self!` are imposed by already existing and well-understood initialization logic, so the provided guarantees don't really come at the cost of much clarity.

On Jun 9, 2017, at 2:23 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 07:12 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
I think a good approach would be to have `self = nil` only mean `the initializer is going to fail` because if your type is ExpressibleByNilLiteral, it means that the `nil` of your type already carries the same meaning as if your type was not ExpressibleByNilLiteral and was an optional instead, so having a failable initializer doesn't really make sense in that case (since you could've initialized `self` to its own `nil` in case of failure). Still, some valid use cases may exist, so the natural (and quite intuitive) way to circumvent this would be to call `self.init(nilLiteral: ())` directly.

So you would create a special rule that `self = nil` means a different thing in an initializer than it does in a function? Essentially, then, you’re creating your own variation on an implicitly unwrapped optional, where `self` is of type `inout Self?` for assignment in initializers only but not for any other purpose. Implicitly unwrapped optionals are hard to reason about, and having a variation on it would be even harder to understand. I don’t think this is a workable design.

It might be possible to have `self` be of type `inout Self?`; however, I do think Greg is right that it would create more boilerplate than the current situation.

On Jun 9, 2017, at 2:07 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

On Fri, Jun 9, 2017 at 06:56 Gor Gyolchanyan <gor@gyolchanyan.com <mailto:gor@gyolchanyan.com>> wrote:
The type of `self` could remain `inout Self` inside the failable initializer. The ability to assign nil would be a compiler magic (much like `return nil` is compiler magic) that is meant to introduce uniformity to the initialization logic.

The idea is to define all different ways initialization can take place and expand them to be used uniformly on both `self` and all its members, as well as remove the ways that do not make sense for their purpose.

Currently, there are 3 ways of initializing self as a whole:
1. delegating initializer
2. assigning to self
3. returning nil

#1: The delegating initializer is pretty much perfect at this point, in my opinion, so no changes there.

#2: The only exception in assigning to self is the `nil` inside failable initializers.

#3: The only thing that can be returned from an initializer is `nil`, which is compiler magic, so we can thing of it as a misnomer (because we aren't really **returning** anything).

If, for a second, we forget about potential factory initializers, returning anything from an initializer doesn't make much sense, because an initializer is conceptually meant to bring an existing object in memory to a type-specific valid state. This semantic was very explicitly in Objective-C with `[[MyType alloc] init]`. Especially since even syntactically, the initializer does not specify any return type, the idea of returning from an initializer is counter-intuitive both syntactically and semantically.

The actual *behavior* of `return nil` is very sensible, so the behavior, I imagine `self = nil`, would largely mean the same (except not needed to return immediately and allowing non-self-accessing code to be executed before return). Being able to assign `nil` to a non-optional (ExpressibleByNilLiteral doesn't count) may feel a bit wonky,

What happens when Self is ExpressibleByNilLiteral and you want to initialize self to nil? That is what `self = nil` means if `self` is of type `inout Self`. If `self` is of type `inout Self` and Self is not ExpressibleByNilLiteral, then it must be an error to assign nil to self. Anything else does not make sense, unless `self` is of type `inout Self?`.

but not as wonky as returning nil from something that is meant to initialize an object in-place and doesn't look like it should return anything.

# Factory Initializers

In case of factory initializers, the much discussed `factory init` syntax could completely flip this logic, but making the initializer essentially a static function that returns an object. In this case the initializer could be made to specify the return type (that is the supertype of all possible factory-created objects) and assigning to self would be forbidden because there is not self yet:

extension MyProtocol {

public factory init(weCool: Bool) -> MyProtocol {
self = MyImpl() // error: cannot assign to `self` in a factory initializer
self.init(...) // error: cannot make a delegating initializer call in a factory initializer
if weCool {
return MyCoolImpl()
} else {
return MyUncoolImpl()
}
}

}

# In-place Member Initializers

In addition, member initialization currently is only possible with #2 (as in `self.member = value`), which could be extended in a non-factory initializer to be initializable in-place like this:

self.member.init(...)

This would compliment the delegating initialization syntax, while giving a more reliable performance guarantee that this member will not be copy-initialized.

On Jun 9, 2017, at 1:32 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

If `self` is not of type `inout Self?`, then what is the type of `self` such that you may assign it a value of `nil`?

It certainly cannot be of type `inout Self`, unless `Self` conforms to `ExpressibleByNilLiteral`, in which case you are able to assign `self = nil` an unlimited number of times–but that has a totally different meaning.

Could `self` be of type `inout Self!`? Now that implicitly unwrapped optionals are no longer their own type, I’m not sure that’s possible. But even if it were, that seems unintuitive and potentially error-prone.

So I think Greg is quite right that, to enable this feature, `self` would have to be of type `inout Self?`–which is intriguing but potentially more boilerplatey than the status quo.
On Fri, Jun 9, 2017 at 05:24 Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Good point, but not necessarily.
Since you cannot access `self` before it being fully initialized and since `self` can only be initialized once, this would mean that after `self = nil`, you won't be allowed to access `self` in your initializer at all.You'll be able to do any potential, cleanup though.
Also, since there can be only one `self = nil`, there's no reason to treat `self` as `inout Self?`, because the only place it can be `nil` is the place it cannot be accessed any more.

On Jun 9, 2017, at 7:45 AM, Greg Parker <gparker@apple.com <mailto:gparker@apple.com>> wrote:

On Jun 8, 2017, at 5:09 AM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

1. Arbitrary `self` Assignments In Intializers

The first ideas is to allow `self = nil` inside failable initializers (essentially making `self` look like `inout Self?` instead of `inout Self` with magical `return nil`), so that all initializers uniformly can be written in `self = ...` form for clarity and convenience purposes. This should, theoretically, be nothing but a `defer { return nil }` type of rewrite, so I don't see any major difficulties implementing this. This is especially useful for failable-initializing enums where the main switch simply assigns to self in all cases and the rest of the initializer does some post-processing.

I don't see how to avoid source incompatibility and uglification of failable initializer implementations here. Allowing `self = nil` inside a failable initializer would require `self` to be an optional. That in turn would require every use of `self` in the initializer to be nil-checked or forced. I don't think that loss everywhere outweighs the gain of `self = nil` in some places.

--
Greg Parker gparker@apple.com <mailto:gparker@apple.com> Runtime Wrangler

_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

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