I have a class with a property that needs to be really *really* lazy. So
lazy, in fact, that when you assign to that property, the class actually
stores a closure of what you assigned, which is only evaluated if and when
you actually attempt to read the property.
Simplified:
class Foo {
private var valueSource: () -> Bar
private var valueCache: Bar?
var value: Bar {
get {
if let v = valueCache { return v }
let w = valueSource()
valueCache = w
return w
}
set {
/* ??? */
}
}
// I want this function's logic to go in the setter above
func setValue(_ v: @escaping@autoclosure () -> Bar) {
valueSource = v
valueCache = nil
}
}
The goal is to be able to write things like “someFoo.value = bar1 / bar2”
(or even more complex expressions) and not evaluate them until/unless the
result is actually needed.
Currently I am using “someFoo.setValue( bar1 / bar2 )”, which is not nearly
as ergonomic as the assignment syntax. So, is there a way to make this work?
You can have valueSource store a closure that captures the autoclosure value. For example,
set {
valueSource = { newValue }
}
Slava
···
On Sep 11, 2017, at 11:04 AM, Nevin Brackett-Rozinsky via swift-users <swift-users@swift.org> wrote:
Hi, quick question here:
I have a class with a property that needs to be really *really* lazy. So lazy, in fact, that when you assign to that property, the class actually stores a closure of what you assigned, which is only evaluated if and when you actually attempt to read the property.
Simplified:
class Foo {
private var valueSource: () -> Bar
private var valueCache: Bar?
var value: Bar {
get {
if let v = valueCache { return v }
let w = valueSource()
valueCache = w
return w
}
set {
/* ??? */
}
}
// I want this function's logic to go in the setter above
func setValue(_ v: @escaping@autoclosure () -> Bar) {
valueSource = v
valueCache = nil
}
}
The goal is to be able to write things like “someFoo.value = bar1 / bar2” (or even more complex expressions) and not evaluate them until/unless the result is actually needed.
Currently I am using “someFoo.setValue( bar1 / bar2 )”, which is not nearly as ergonomic as the assignment syntax. So, is there a way to make this work?
I have a class with a property that needs to be really *really* lazy. So lazy, in fact, that when you assign to that property, the class actually stores a closure of what you assigned, which is only evaluated if and when you actually attempt to read the property.
Simplified:
class Foo {
private var valueSource: () -> Bar
private var valueCache: Bar?
var value: Bar {
get {
if let v = valueCache { return v }
let w = valueSource()
valueCache = w
return w
}
set {
/* ??? */
}
}
// I want this function's logic to go in the setter above
func setValue(_ v: @escaping@autoclosure () -> Bar) {
valueSource = v
valueCache = nil
}
}
The goal is to be able to write things like “someFoo.value = bar1 / bar2” (or even more complex expressions) and not evaluate them until/unless the result is actually needed.
Currently I am using “someFoo.setValue( bar1 / bar2 )”, which is not nearly as ergonomic as the assignment syntax. So, is there a way to make this work?
Unless I'm missing something, can't you just call the closure that you passed to the init ? Or do you want to use a different closure ?
You could always have a var that is a tuple, with one part being the value and the other the closure.
But the expression that is assigned to the property will be eagerly evaluated to produce `newValue`. So this will not accomplish what Nevin is trying to do.
···
On Sep 11, 2017, at 3:08 PM, Slava Pestov via swift-users <swift-users@swift.org> wrote:
You can have valueSource store a closure that captures the autoclosure value. For example,
set {
valueSource = { newValue }
}
Slava
On Sep 11, 2017, at 11:04 AM, Nevin Brackett-Rozinsky via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
Hi, quick question here:
I have a class with a property that needs to be really *really* lazy. So lazy, in fact, that when you assign to that property, the class actually stores a closure of what you assigned, which is only evaluated if and when you actually attempt to read the property.
Simplified:
class Foo {
private var valueSource: () -> Bar
private var valueCache: Bar?
var value: Bar {
get {
if let v = valueCache { return v }
let w = valueSource()
valueCache = w
return w
}
set {
/* ??? */
}
}
// I want this function's logic to go in the setter above
func setValue(_ v: @escaping@autoclosure () -> Bar) {
valueSource = v
valueCache = nil
}
}
The goal is to be able to write things like “someFoo.value = bar1 / bar2” (or even more complex expressions) and not evaluate them until/unless the result is actually needed.
Currently I am using “someFoo.setValue( bar1 / bar2 )”, which is not nearly as ergonomic as the assignment syntax. So, is there a way to make this work?
No, newValue is a closure here, and valueSource will capture this closure. When valueSource is evaluated, the original closure will be evaluated.
Slava
···
On Sep 11, 2017, at 3:11 PM, Hooman Mehr <hooman@mac.com> wrote:
But the expression that is assigned to the property will be eagerly evaluated to produce `newValue`. So this will not accomplish what Nevin is trying to do.
On Sep 11, 2017, at 3:08 PM, Slava Pestov via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
You can have valueSource store a closure that captures the autoclosure value. For example,
set {
valueSource = { newValue }
}
Slava
On Sep 11, 2017, at 11:04 AM, Nevin Brackett-Rozinsky via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
Hi, quick question here:
I have a class with a property that needs to be really *really* lazy. So lazy, in fact, that when you assign to that property, the class actually stores a closure of what you assigned, which is only evaluated if and when you actually attempt to read the property.
Simplified:
class Foo {
private var valueSource: () -> Bar
private var valueCache: Bar?
var value: Bar {
get {
if let v = valueCache { return v }
let w = valueSource()
valueCache = w
return w
}
set {
/* ??? */
}
}
// I want this function's logic to go in the setter above
func setValue(_ v: @escaping@autoclosure () -> Bar) {
valueSource = v
valueCache = nil
}
}
The goal is to be able to write things like “someFoo.value = bar1 / bar2” (or even more complex expressions) and not evaluate them until/unless the result is actually needed.
Currently I am using “someFoo.setValue( bar1 / bar2 )”, which is not nearly as ergonomic as the assignment syntax. So, is there a way to make this work?
Oh I see, the property itself does not have autoclosure type.
Slava
···
On Sep 11, 2017, at 3:52 PM, Slava Pestov <spestov@apple.com> wrote:
No, newValue is a closure here, and valueSource will capture this closure. When valueSource is evaluated, the original closure will be evaluated.
Slava
On Sep 11, 2017, at 3:11 PM, Hooman Mehr <hooman@mac.com <mailto:hooman@mac.com>> wrote:
But the expression that is assigned to the property will be eagerly evaluated to produce `newValue`. So this will not accomplish what Nevin is trying to do.
On Sep 11, 2017, at 3:08 PM, Slava Pestov via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
You can have valueSource store a closure that captures the autoclosure value. For example,
set {
valueSource = { newValue }
}
Slava
On Sep 11, 2017, at 11:04 AM, Nevin Brackett-Rozinsky via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
Hi, quick question here:
I have a class with a property that needs to be really *really* lazy. So lazy, in fact, that when you assign to that property, the class actually stores a closure of what you assigned, which is only evaluated if and when you actually attempt to read the property.
Simplified:
class Foo {
private var valueSource: () -> Bar
private var valueCache: Bar?
var value: Bar {
get {
if let v = valueCache { return v }
let w = valueSource()
valueCache = w
return w
}
set {
/* ??? */
}
}
// I want this function's logic to go in the setter above
func setValue(_ v: @escaping@autoclosure () -> Bar) {
valueSource = v
valueCache = nil
}
}
The goal is to be able to write things like “someFoo.value = bar1 / bar2” (or even more complex expressions) and not evaluate them until/unless the result is actually needed.
Currently I am using “someFoo.setValue( bar1 / bar2 )”, which is not nearly as ergonomic as the assignment syntax. So, is there a way to make this work?