[swift-evolution] [Review] SE-0018 Flexible Memberwise Initialization
plx
plxswift at icloud.com
Sat Jan 9 07:36:50 CST 2016
> On Jan 8, 2016, at 12:51 PM, Matthew Johnson <matthew at anandabits.com> wrote:
>
> Are you suggesting that this attribute would be applied to a specific initializer? Or would this be shared by all memberwise initializers of the type in some way?
I meant it as a type-level declaration.
The mental model here is that in many cases, a type with multiple public initializers winds up (or at least should wind up) like this:
- there’s a common “package” comprised of:
- the input parameters (e.g. init args)
- the boilerplate assignments (in the init)
- each init has some additional parameters/logic not shared with the other
For another example, this is lightly-adapted from actual code:
class PlayerItemWrapper : NSObject {
let previewInfo: PreviewInfo
let itemDescriptor: ItemDescriptor
let metricCollector: MetricCollector
let playerItem: AVPlayerItem
// assume trivial assignments followed by observation-setup logic:
required init(previewInfo: PreviewInfo, itemDescriptor: ItemDescriptor, metricCollector: MetricCollector, playerItem: AVPlayerItem)
// these exist for convenience only; we have them b/c we don’t want to directly use
// the corresponding AVPlayerItem convenience methods, since we also want to
// control some of automatically loaded keys (etc.)
convenience init(previewInfo: PreviewInfo, itemDescriptor: ItemDescriptor, metricCollector: MetricCollector, asset: AVAsset)
convenience init(previewInfo: PreviewInfo, itemDescriptor: ItemDescriptor, metricCollector: MetricCollector, assetURL: NSURL)
convenience init(previewInfo: PreviewInfo, itemDescriptor: ItemDescriptor, metricCollector: MetricCollector, assetDescriptor: AssetDescriptor)
}
…where you can easily see these inits have the structure of a “common package” + per-init details.
Under the organization above, it then makes sense to me to have a type-level declaration that is able to declare that type’s “official” common package, which would let the above be condensed into something like:
class PlayerItemWrapper : NSObject {
@memberwise(previewInfo, itemDescriptor, metricCollector)
// ^ need to be explicit here to *omit* playerItem, unless we
// also plan to immediately have an @nomemberwise declaration
// we can apply to individual properties
let previewInfo: PreviewInfo
let itemDescriptor: ItemDescriptor
let metricCollector: MetricCollector
let playerItem: AVPlayerItem
// assume trivial assignments followed by observation-setup logic:
memberwise required init(..., playerItem: AVPlayerItem)
// these exist for convenience only (and would need a way to forward the …
// to the required init, e.g. `self.init(…, playerItem: _)`, which is seems to be
// noted as a future direction in the current proposal
memberwise convenience init(…, asset: AVAsset)
memberwise convenience init(..., assetURL: NSURL)
memberwise convenience init(..., assetDescriptor: AssetDescriptor)
}
…and because writing out such parameter lists explicitly is a bit of a pain, the hope is that it’d also be possible to simply write e.g. @memberwise w/out an explicit list and get some automatically-inferred list synthesized on your behalf wherever possible.
Hope this clears up the kind of thing I was trying to sketch earlier. It is at a different point in the flexibility/feature spectrum for sure, and not thought-through too thoroughly either.
I also made a significant earlier error: it shouldn’t be an error if some @memberwise’s $parameterList was *incomplete*, the only error is if it contains invalid/unrecognized names.
> I don’t think applying this to a specific initializer gains enough over just writing the initializer manually to be worthwhile. If we were going to do something specific to a single initializer, something along the lines of David’s suggestion makes the most sense to me.
>
> On the other hand, if you are suggesting something type-wide that would be shared by all memberwise initializers, this is really an alternate way to accomplish an opt-in model. Rather than applying an attribute to properties you would have a declaration specify which properties are included in memberwise initializers, with the ability to specify order, labels, and defaults if necessary.
This is what I meant, essentially. An explicit @memberwise as per the above saves minimal effort if you had to do it on a per-init basis, but in scenarios with a bunch of basic parameters + various convenience inits for the remaining parameters it could still be a net win.
> That might be a reasonable syntax for an opt-in model. As noted in the proposal, an opt-in model could be added by a future enhancement and would be used in place of the automatic model if the opt-in syntax was present.
If this goes anywhere I am hoping someone will improve the syntax, actually, what I sketched seems clunky and non-idiomatic.
In any case, having seen how this discussion has gone I think it’s safe that at least in hindsight starting from the purely-automatic/purely-inferred synthesis standpoint may ultimately have made this proposal than it needs to have been.
It’s a *really* good goal — I’d like to be able to get the memberwise init synthesized automatically where possible! — and I think within the design constraints you’ve been working under it may not be possible to do it that much better than as per your proposal…but I think the conclusion here is that “it seemed plausible to extend the memberwise-init synthesis like this, but if you work through it in enough detail to make it concrete, it has a surprising amount of intrinsic complexity/inference rules/edge-cases to worry about”.
That’s my overall 2c here (along with what’s in the earlier emails).
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160109/d084f55d/attachment.html>
More information about the swift-evolution
mailing list