[swift-evolution] [Proposal] Property behaviors
Tino Heth
2th at gmx.de
Sat Jan 16 06:39:33 CST 2016
I'm always in favor of removing special cases (like lazy and willSet/didSet), so the idea of property behaviors itself is very appealing to me.
There's one downside, though:
The proposal makes some keywords obsolete, but introduces a whole bunch of new stuff in exchange — and all of this only can be used with properties…
I hope you agree with me that there is merit in keeping the language small (it's called "Swift", not "Turkey" ;-), and that the proposal would improve if it's possible to slim it down.
Imho the first step to add property behaviors should be refining how properties are modeled in Swift:
In many languages, properties are represented as a pair of methods (setter and getter), and their absence has several downsides (functional programming works best with functions ;-).
As soon as there is a way to read and write properties in a functional way, their behaviors could be expressed in a universal manner:
Afaics, all major use cases for behaviors can be implemented as simple "decorators" — in fact, I could simulate most examples from the proposal in a tiny playground (a part of it is attached).
Of course, the simulation is ugly, but I am confident that some nice ideas would come up if properties were more accessible.
Best regards,
Tino
//: Properties are modelled as a getter/setter pair
struct Property<T> {
var get: Void -> T
var set: (T) -> Void
}
class Test {
// A field to store the actual data
var mValue: Int?
// This is our "pseudo-property": Just imaging that `self.value.get` maps to `self.value`
var value = Property(get: { return 0 }, set: { Int in } )
init() {
// This is necessary because we need `self` to fake the getter/setter
value = Property(get: { return self.mValue! }, set: { self.mValue = $0 })
}
}
/*:
Behaviors are modelled as a transformation:
The take a set of functions and return another set the is extended according to the behavior.
A real implementation would gain more clarity from the (deprecated...) currying-syntax
*/
func didSetBehavior<T>(property: Property<T>, didSet: (T) -> Void) -> Property<T> {
func setter(value: T) {
property.set(value)
didSet(value)
}
return Property(get: property.get, set: setter)
}
class DidSet: Test {
//: Imagine we have no superclass, and `value` is declared like
/*:
var[didSetBehavior {
print("New value is \($0)")
}] value: Int
*/
override init() {
super.init()
value = didSetBehavior(value) {
print("New value is \($0)")
}
}
}
func willSetBehavior<T>(property: Property<T>)(allow: (old: T, new: T) -> Bool) -> Property<T> {
func setter(new: T) {
if allow(old: property.get(), new: new) {
property.set(new)
}
}
return Property(get: property.get, set: setter)
}
class WillSet: Test {
override init() {
super.init()
self.value = willSetBehavior(value)(allow: { return $0 != $1 } )
}
}
class WillSetDidSet: WillSet {
override init() {
super.init()
self.value = didSetBehavior(value) {
print("New value is \($0)")
}
}
}
func copyBehavior<T: NSCopying>(property: Property<T>) -> Property<T> {
func performCopy(value: T) {
let copy = value.copyWithZone(nil) as! T
property.set(copy)
}
return Property(get: property.get, set: performCopy)
}
class Copy {
var mValue = NSString()
var value = Property(get: { return NSString() }, set: { NSString in return } )
init() {
value = Property(get: { return self.mValue }, set: { self.mValue = $0 })
self.value = copyBehavior(value)
}
}
let copyTest = Copy()
print(copyTest.value.get())
var mutableString = NSMutableString(string: "Mutable")
copyTest.value.set(mutableString)
mutableString.appendString(" string")
print(copyTest.value.get())
func decorate<In, Out, Discard>(function: (In) -> Out, decoration: (In) -> Discard) -> (In) -> Out {
func result(input: In) -> Out {
decoration(input)
return function(input)
}
return result
}
class FuncTest {
var f = { (input: String) in
print(input)
}
init() {
self.f = decorate(f) { input in
print("Our input is \(input)")
}
}
}
FuncTest().f("duplicated")
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160116/3fc09dac/attachment-0001.html>
More information about the swift-evolution
mailing list