[swift-evolution] [Review] SE-0018 Flexible Memberwise Initialization

Kevin Ballard kevin at sb.org
Thu Jan 7 15:37:16 CST 2016


On Thu, Jan 7, 2016, at 01:31 PM, Kevin Ballard wrote:
> On Thu, Jan 7, 2016, at 07:12 AM, Matthew Johnson wrote:
>>> As for my concern, it's with the following rule:
>>>
>>>> If the initializer body assigns to a var property that received
>>>> memberwise initialization synthesis report a warning. It is
>>>> unlikely that overwriting the value provided by the caller is the
>>>> desired behavior.
>>>
>>> I understand why you put this in there, but this is a warning that
>>> cannot be suppressed and will make it impossible to use a memberwise
>>> initializer for perfectly legitimate cases where you do in fact want
>>> to mutate the property after it's been assigned to.
>>
>> For normal initializers I agree with you.  However, I think it’s a
>> reasonable for callers to assume that if you expose a property via
>> memberwise initialization the post-initialization value will match
>> the value they provide.  This warning is intended to alert you to the
>> fact that you are violating that reasonable assumption.
>
> I think that's a reasonable assumption in many cases, but I don't like
> the fact that the feature cannot be used at all in the rare case where
> it actually makes sense to mutate the value.
>
>> Do you have an example of where you would want a caller to initialize
>> a property, but then overwrite the value they provide *during
>> initialization*?
>
> Sure, how about something like a Rect type that always guarantees it's
> in "standard" form (e.g. no negative sizes):
>
> struct StandardRect {    var origin: CGPoint    var size: CGSize {
> didSet {            // ensure standardized form here        }    }
>
> memberwise init(...) {        if size.width < 0 {            origin.x
> += size.width            size.width = -size.width        }        if
> size.height < 0 {            origin.y += size.height
> size.height = -size.height        }    } }
>
> Or how about a struct that represents a URL request complete with
> headers, and forces the inclusion of Content-Type:
>
> struct URLRequest {    var headers: [String: String] = [:]    // ...
> other properties here ...    memberwise init(contentType: String, ...)
> {        headers["Content-Type"] = contentType    } }

Here's an even better example, since it matches some code I actually
already have in a production app. Assuming that the "..." placeholder
can go anywhere (which seems reasonable), I have extensions on CGRect
and friends that could use memberwise init instead to be written like

extension CGRect {    memberwise init(..., roundedToScale: CGFloat) }

This method takes the components of a rect, as well as a scale, and it
properly rounds the components so that the rect falls along pixel
boundaries if displayed on a screen with the given scale.

-Kevin Ballard
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160107/8a400362/attachment.html>


More information about the swift-evolution mailing list