Member wise initializer doesn't work with default-initialized const properties


(Neil Faiman) #1

Using the default Swift with Xcode 7.3.1.

It appears that you cannot use the implicit memberwise initializer with a struct that has “let” properties with default values.

This works perfectly:

    struct CF {
        let prop: Int
    }
    let cf = CF(prop: 1)

But give the property a default value:

    struct CF {
        let prop: Int = 0
    }
    let cf = CF(prop: 1)

And now the compiler complains:

    error: argument passed to call that takes no arguments
    let cf = CF(prop: 1)
               ~~~~~~~^~

I don’t believe that the Apple _The Swift Programming Language_ mentions this restriction.

  Neil Faiman


(Jeremy Pereira) #2

Using the default Swift with Xcode 7.3.1.

It appears that you cannot use the implicit memberwise initializer with a struct that has “let” properties with default values.

It’s not a default value, it is *the* value

I don’t believe that the Apple _The Swift Programming Language_ mentions this restriction.

Chapter “The Basics”, section “Constants and Variables”

“The value of a constant cannot be changed once it is set”.

···

On 16 May 2016, at 22:37, Neil Faiman via swift-users <swift-users@swift.org> wrote:

  Neil Faiman
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Neil Faiman) #3

But:

“You can provide a default value for a stored property as part of its definition, as described in Default Property Values. You can also set and modify the initial value for a stored property during initialization. This is true even for constant stored properties, as described in Assigning Constant Properties During Initialization.” (Classes and Structures / Stored Properties)

···

On May 17, 2016, at 7:03 AM, Jeremy Pereira <jeremy.j.pereira@googlemail.com> wrote:

On 16 May 2016, at 22:37, Neil Faiman via swift-users <swift-users@swift.org> wrote:

Using the default Swift with Xcode 7.3.1.

It appears that you cannot use the implicit memberwise initializer with a struct that has “let” properties with default values.

It’s not a default value, it is *the* value

I don’t believe that the Apple _The Swift Programming Language_ mentions this restriction.

Chapter “The Basics”, section “Constants and Variables”

“The value of a constant cannot be changed once it is set”.


(Jeremy Pereira) #4

And did you try clicking through to “Assigning Constant Properties During Initialisation”? It says this:

“Once a constant property is assigned a value, it cannot be further modified”

I would argue that in

struct A
{
    let foo = 42
}

foo has been assigned a value and cannot be further modified. The only way your interpretation can work is if the assignment in the declaration line is deemed to occur somehow before initialisation, which is a valid interpretation, but since

struct A
{
    let foo = 42
    init(foo: Int)
    {
        self.foo = foo
    }
}

is an error, it looks like the compiler writers went with my interpretation.

I certainly concede that it looks like the passage you found contradicts the two passages I found. Perhaps one of us should raise a bug to clarify the meaning and - if you are correct - fix the compiler.

···

On 17 May 2016, at 15:48, Neil Faiman <neil@faiman.org> wrote:

On May 17, 2016, at 7:03 AM, Jeremy Pereira <jeremy.j.pereira@googlemail.com> wrote:

On 16 May 2016, at 22:37, Neil Faiman via swift-users <swift-users@swift.org> wrote:

Using the default Swift with Xcode 7.3.1.

It appears that you cannot use the implicit memberwise initializer with a struct that has “let” properties with default values.

It’s not a default value, it is *the* value

I don’t believe that the Apple _The Swift Programming Language_ mentions this restriction.

Chapter “The Basics”, section “Constants and Variables”

“The value of a constant cannot be changed once it is set”.

But:

“You can provide a default value for a stored property as part of its definition, as described in Default Property Values. You can also set and modify the initial value for a stored property during initialization. This is true even for constant stored properties, as described in Assigning Constant Properties During Initialization.” (Classes and Structures / Stored Properties)


(Jens Alfke) #5

You can assign the value of an as-yet-unassigned ‘let’ property, once. If that happens in the default initialization phase (before any initializer methods run), then you’ve used up that chance. The initializer would be setting a second value, which isn’t allowed.

Read up on the phases of initialization in the Swift book.

—Jens

···

On May 17, 2016, at 7:48 AM, Neil Faiman via swift-users <swift-users@swift.org> wrote:

“You can provide a default value for a stored property as part of its definition, as described in Default Property Values. You can also set and modify the initial value for a stored property during initialization. This is true even for constant stored properties, as described in Assigning Constant Properties During Initialization.” (Classes and Structures / Stored Properties)


(Matthew Johnson) #6

Using the default Swift with Xcode 7.3.1.

It appears that you cannot use the implicit memberwise initializer with a struct that has “let” properties with default values.

It’s not a default value, it is *the* value

I don’t believe that the Apple _The Swift Programming Language_ mentions this restriction.

Chapter “The Basics”, section “Constants and Variables”

“The value of a constant cannot be changed once it is set”.

But:

“You can provide a default value for a stored property as part of its definition, as described in Default Property Values. You can also set and modify the initial value for a stored property during initialization. This is true even for constant stored properties, as described in Assigning Constant Properties During Initialization.” (Classes and Structures / Stored Properties)

And did you try clicking through to “Assigning Constant Properties During Initialisation”? It says this:

“Once a constant property is assigned a value, it cannot be further modified”

I would argue that in

struct A
{
   let foo = 42
}

foo has been assigned a value and cannot be further modified. The only way your interpretation can work is if the assignment in the declaration line is deemed to occur somehow before initialisation, which is a valid interpretation, but since

struct A
{
   let foo = 42
   init(foo: Int)
   {
       self.foo = foo
   }
}

is an error, it looks like the compiler writers went with my interpretation.

I certainly concede that it looks like the passage you found contradicts the two passages I found. Perhaps one of us should raise a bug to clarify the meaning and - if you are correct - fix the compiler.

This behavior was discussed quite extensively during in the threads and review of my memberwise init proposal. It is likely to be revised in some way when memberwise init is revisited, perhaps in Swift 4. You may wish to look up the feedback the core team gave at the conclusion of the review if you're interested in details.

···

Sent from my iPad

On May 17, 2016, at 11:42 AM, Jeremy Pereira via swift-users <swift-users@swift.org> wrote:

On 17 May 2016, at 15:48, Neil Faiman <neil@faiman.org> wrote:
On May 17, 2016, at 7:03 AM, Jeremy Pereira <jeremy.j.pereira@googlemail.com> wrote:

On 16 May 2016, at 22:37, Neil Faiman via swift-users <swift-users@swift.org> wrote:

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