[Pitch] inout with capture variable


(frogcjn) #1

for example:

var a = 1

let block = { [inout a] in
  a += 1
}

block()
block()

print(a) // 3


(Daniel Resnick) #2

You can currently achieve the same result if you remove `[inout a]` since
`var`s are captured by reference.

···

On Wed, Oct 5, 2016 at 9:06 PM, Cao Jiannan via swift-evolution < swift-evolution@swift.org> wrote:

for example:

var a = 1

let block = { [inout a] in
        a += 1
}

block()
block()

print(a) // 3

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


(Mark Lacey) #3

for example:

var a = 1

let block = { [inout a] in
  a += 1
}

block()
block()

print(a) // 3

This is already how captures work by default in closures and nested functions in Swift:

var a = 1

let block = { a += 1 }

block()
block()

print(a) // prints 3

If you want to capture something immutably you can put it in the capture list:

var a = 1
let block = { [a] in a += 1 } // error: left side of mutating operator isn't mutable: 'a' is a 'let' constant

Mark

···

On Oct 5, 2016, at 9:06 PM, Cao Jiannan via swift-evolution <swift-evolution@swift.org> wrote:

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


(frogcjn) #4

so if developer want to capture an variable inference, must declare a new variable.

class A {
    var value = 1
    
    func test() -> () -> Int {
        var capturedValue = self.value
        let editInfo = { () -> Int in
            capturedValue += 1
            return capturedValue
        }
        return editInfo
    }
}

let a = A()

let editInfo = a.test()
print(editInfo()) // 2
print(a.value) // 1
print(editInfo()) // 3
print(a.value) // 1

what about:

class A {
    var value = 1
    
    func test() -> () -> Int {
        let editInfo = { [inout value] () -> Int in
            capturedValue += 1
            return capturedValue
        }
        return editInfo
    }
}

let a = A()

let editInfo = a.test()
print(editInfo()) // 2
print(a.value) // 2
print(editInfo()) // 3
print(a.value) // 3

···

> On Oct 5, 2016, at 9:06 PM, Cao Jiannan via swift-evolution<swift-evolution@swift.org>wrote:
>
> for example:
>
> var a = 1
>
> let block = { [inout a] in
> a += 1
> }
>
> block()
> block()
>
> print(a) // 3
This is already how captures work by default in closures and nested functions in Swift:

var a = 1

let block = { a += 1 }

block()
block()

print(a) // prints 3

If you want to capture something immutably you can put it in the capture list:

var a = 1
let block = { [a] in a += 1 } // error: left side of mutating operator isn't mutable: 'a' is a 'let' constant

Mark

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


(Mark Lacey) #5

so if developer want to capture an variable inference, must declare a new variable.

I don’t follow what you mean here.

class A {
    var value = 1
    
    func test() -> () -> Int {
        var capturedValue = self.value
        let editInfo = { () -> Int in
            capturedValue += 1
            return capturedValue
        }
        return editInfo
    }
}

let a = A()

let editInfo = a.test()
print(editInfo()) // 2
print(a.value) // 1
print(editInfo()) // 3
print(a.value) // 1

what about:

class A {
    var value = 1
    
    func test() -> () -> Int {
        let editInfo = { [inout value] () -> Int in
            capturedValue += 1
            return capturedValue
        }
        return editInfo
    }
}

let a = A()

let editInfo = a.test()
print(editInfo()) // 2
print(a.value) // 2
print(editInfo()) // 3
print(a.value) // 3

I’m not quite sure what you’re getting at, but this prints what you’re expecting in the output you have in the comments:

class A {
    var value = 1
    
    func test() -> () -> Int {
        let editInfo = { () -> Int in
            self.value += 1
            return self.value
        }
        return editInfo
    }
}

let a = A()

let editInfo = a.test()
print(editInfo()) // 2
print(a.value) // 2
print(editInfo()) // 3
print(a.value) // 3

Mark

···

On Oct 5, 2016, at 10:07 PM, Cao Jiannan <frogcjn@163.com> wrote:

> > On Oct 5, 2016, at 9:06 PM, Cao Jiannan via swift-evolution<swift-evolution@swift.org <mailto:swift-evolution@swift.org>>wrote:
> >
> > for example:
> >
> > var a = 1
> >
> > let block = { [inout a] in
> > a += 1
> > }
> >
> > block()
> > block()
> >
> > print(a) // 3
> This is already how captures work by default in closures and nested functions in Swift:
>
> var a = 1
>
> let block = { a += 1 }
>
> block()
> block()
>
> print(a) // prints 3
>
>
> If you want to capture something immutably you can put it in the capture list:
>
> var a = 1
> let block = { [a] in a += 1 } // error: left side of mutating operator isn't mutable: 'a' is a 'let' constant
>
> Mark
>
> >
> >
> > _______________________________________________
> > swift-evolution mailing list
> > swift-evolution@swift.org <mailto:swift-evolution@swift.org>
> > https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>


(frogcjn) #6

I just want to demo how the inout capture works.
the demo code just want to capture value avoiding capture self.

···

> On Oct 5, 2016, at 10:07 PM, Cao Jiannan<frogcjn@163.com(mailto:frogcjn@163.com)>wrote:
> so if developer want to capture an variable inference, must declare a new variable.
I don’t follow what you mean here.

>
> classA {
> varvalue = 1
>
> functest() ->() ->Int{
> varcapturedValue =self.value
> leteditInfo = { () ->Intin
> capturedValue += 1
> returncapturedValue
> }
> returneditInfo
> }
> }
>
> leta =A()
>
> leteditInfo =a.test()
> print(editInfo()) // 2
> print(a.value) // 1
>
> print(editInfo()) // 3
>
> print(a.value) // 1
>
> what about:
>
> classA {
> varvalue = 1
>
> functest() ->() ->Int{
> leteditInfo = { [inout value] () ->Intin
> capturedValue += 1
> returncapturedValue
> }
> returneditInfo
> }
> }
>
> leta =A()
>
> leteditInfo =a.test()
> print(editInfo()) // 2
> print(a.value) // 2
>
>
> print(editInfo()) // 3
>
> print(a.value) // 3
>
>
>
>
I’m not quite sure what you’re getting at, but this prints what you’re expecting in the output you have in the comments:

class A {
var value = 1

func test() ->() ->Int {
let editInfo = { () ->Int in
self.value += 1
return self.value
}
return editInfo
}
}

let a = A()

let editInfo = a.test()
print(editInfo()) // 2
print(a.value) // 2
print(editInfo()) // 3
print(a.value) // 3

Mark

>
> >>On Oct 5, 2016, at 9:06 PM, Cao Jiannan via swift-evolution<swift-evolution@swift.org(mailto:swift-evolution@swift.org)>wrote:
> >>
> >>for example:
> >>
> >>var a = 1
> >>
> >>let block = { [inout a] in
> >>a += 1
> >>}
> >>
> >>block()
> >>block()
> >>
> >>print(a) // 3
> >This is already how captures work by default in closures and nested functions in Swift:
> >
> >var a = 1
> >
> >let block = { a += 1 }
> >
> >block()
> >block()
> >
> >print(a) // prints 3
> >
> >
> >If you want to capture something immutably you can put it in the capture list:
> >
> >var a = 1
> >let block = { [a] in a += 1 } // error: left side of mutating operator isn't mutable: 'a' is a 'let' constant
> >
> >Mark
> >
> >>
> >>
> >>_______________________________________________
> >>swift-evolution mailing list
> >>swift-evolution@swift.org(mailto:swift-evolution@swift.org)
> >>https://lists.swift.org/mailman/listinfo/swift-evolution
> >
> >
> >