I need to initialize a variable of a class with a closure using the value of some variables of the class.
Since this is not permitted I thought I might solve the problem by declaring it lazy. But this is still rejected by the compiler.
If there are no circular dependencies in initialization of lazy variables this could be allowed, couldn’t it?
Or is this a very big if?
My workaround is ugly: a calculated property + a private variable + an initialized:Bool variable.
On Mon, Jul 4, 2016 at 1:04 PM, J.E. Schotsman via swift-users < swift-users@swift.org> wrote:
Hello,
I need to initialize a variable of a class with a closure using the value
of some variables of the class.
Since this is not permitted I thought I might solve the problem by
declaring it lazy. But this is still rejected by the compiler.
If there are no circular dependencies in initialization of lazy variables
this could be allowed, couldn’t it?
Or is this a very big if?
My workaround is ugly: a calculated property + a private variable + an
initialized:Bool variable.
On Tue, Jul 5, 2016 at 1:04 AM, J.E. Schotsman via swift-users < swift-users@swift.org> wrote:
Hello,
I need to initialize a variable of a class with a closure using the value
of some variables of the class.
Since this is not permitted I thought I might solve the problem by
declaring it lazy. But this is still rejected by the compiler.
If there are no circular dependencies in initialization of lazy variables
this could be allowed, couldn’t it?
Or is this a very big if?
My workaround is ugly: a calculated property + a private variable + an
initialized:Bool variable.
I’ve been hitting this myself. I think it’s a bug -- yes, you are technically in a closure, but the closure does not capture ‘self’ beyond the lifetime of ‘self’. In this context, ’self’ should automatically be ‘unowned’.
Karl
···
On 4 Jul 2016, at 21:12, Mark Dalrymple via swift-users <swift-users@swift.org> wrote:
Here's the one I started with:
lazy var c:Int = {return a*b}()
and ended up with:
lazy var c:Int = {return self.a * self.b}()
It's in a closure, so need to explicitly reference self.
For a closure, you have to call self explicitly unless the closure is mark
as @noescape. Also, in this situation, self is not unowned, as the closure
is not stored, it ran and released. Below, is a situation that you need use
unowned self. Here the closure is stored in variable d instead of running
and releasing.
lazy var d:()->Int = { [unowned self] in
return self.a*self.b
}
Zhaoxin
···
On Tue, Jul 5, 2016 at 3:42 AM, Karl via swift-users <swift-users@swift.org> wrote:
On 4 Jul 2016, at 21:12, Mark Dalrymple via swift-users < > swift-users@swift.org> wrote:
Here's the one I started with:
lazy var c:Int = {return a*b}()
and ended up with:
lazy var c:Int = {return self.a * self.b}()
It's in a closure, so need to explicitly reference self.
Cheers,
++md
I’ve been hitting this myself. I think it’s a bug -- yes, you are
technically in a closure, but the closure does not capture ‘self’ beyond
the lifetime of ‘self’. In this context, ’self’ should automatically be
‘unowned’.
In this specific case, when you are initialising from a closure, there is no need to make the capture of ‘self’ explicit and it’s totally safe for it to be unowned. You can’t invoke the closure without going through a valid instance, and that instance always owns the closure and never the other way around.
···
On 5 Jul 2016, at 03:47, Zhao Xin <owenzx@gmail.com> wrote:
No, it is not a bug.
For a closure, you have to call self explicitly unless the closure is mark as @noescape. Also, in this situation, self is not unowned, as the closure is not stored, it ran and released. Below, is a situation that you need use unowned self. Here the closure is stored in variable d instead of running and releasing.
lazy var d:()->Int = { [unowned self] in
return self.a*self.b
}
The compiler is not smart enough to treat this as you think, nor it will be
designed to. According to the documents, it is the developer‘s burden to
add @noescape or weak or unowned. So I disagree it is a bug.
Zhaoxin
···
On Sat, Jul 9, 2016 at 7:30 AM, Karl <razielim@gmail.com> wrote:
On 5 Jul 2016, at 03:47, Zhao Xin <owenzx@gmail.com> wrote:
No, it is not a bug.
For a closure, you have to call self explicitly unless the closure is mark
as @noescape. Also, in this situation, self is not unowned, as the closure
is not stored, it ran and released. Below, is a situation that you need use
unowned self. Here the closure is stored in variable d instead of running
and releasing.
lazy var d:()->Int = { [unowned self] in
return self.a*self.b
}
Zhaoxin
In this specific case, when you are initialising from a closure, there is
no need to make the capture of ‘self’ explicit and it’s totally safe for it
to be unowned. You can’t invoke the closure without going through a valid
instance, and that instance always owns the closure and never the other way
around.
I know that the compiler doesn’t do this today, but I disagree that it will never have enough information to make inferences like this. It would simply be an adaptation of ARC to Swift - you don’t have these kind of attached lazy closures in Obj-C, so there was never any need for it. They run in the context of the instance just like a getter would, so they should have the same properties as a getter (including implicit ‘self’).
In general though, I think we are moving to “property behaviours”, which may need something like this in general. You would want to use unowned references in a stored property behaviour object; any retains/releases would be unnecessary. I’m sure we’ll talk about it more when that gets further along.
Karl
···
On 9 Jul 2016, at 06:34, Zhao Xin <owenzx@gmail.com> wrote:
The compiler is not smart enough to treat this as you think, nor it will be designed to. According to the documents, it is the developer‘s burden to add @noescape or weak or unowned. So I disagree it is a bug.
Zhaoxin
On Sat, Jul 9, 2016 at 7:30 AM, Karl <razielim@gmail.com <mailto:razielim@gmail.com>> wrote:
On 5 Jul 2016, at 03:47, Zhao Xin <owenzx@gmail.com <mailto:owenzx@gmail.com>> wrote:
No, it is not a bug.
For a closure, you have to call self explicitly unless the closure is mark as @noescape. Also, in this situation, self is not unowned, as the closure is not stored, it ran and released. Below, is a situation that you need use unowned self. Here the closure is stored in variable d instead of running and releasing.
lazy var d:()->Int = { [unowned self] in
return self.a*self.b
}
Zhaoxin
In this specific case, when you are initialising from a closure, there is no need to make the capture of ‘self’ explicit and it’s totally safe for it to be unowned. You can’t invoke the closure without going through a valid instance, and that instance always owns the closure and never the other way around.