I have the following trivial example to show composition:
struct Adjusting<V> {
var value: V {
didSet { value = transform(value) }
}
private var transform: (V) -> (V)
init(initialValue: V, _ transform: @escaping (V) -> (V)) {
self.value = initialValue
self.transform = transform
}
}
@_propertyDelegate
struct Clamping<V: Comparable> {
@Adjusting var value: V
init(initialValue: V, min minimum: V, max maximum: V) {
$value = Adjusting(initialValue: initialValue,
{ max(min($0, maximum), minimum) })
}
}
@_propertyDelegate
struct Min<V: FixedWidthInteger> {
@Clamping var value: V
init(initialValue: V, min minimum: V) {
$value = Clamping(initialValue: initialValue,
min: minimum, max: V.self.max)
}
}
@_propertyDelegate
struct Max<V: FixedWidthInteger> {
@Clamping var value: V
init(initialValue: V, max maximum: V) {
$value = Clamping(initialValue: initialValue,
min: V.self.min, max: maximum)
}
}
class C {
@Adjusting(initialValue: 0, { max(0, $0) }) var a: Int
@Clamping(initialValue: 1, min: 1, max: 7) var b: Int
@Min(initialValue: 0, min: 7) var c: Int
}
Is there any way to change the syntax so that it's not necessary to provide an initialValue to the constructors? I'd much rather see something like this:
@Clamping(min: 1, max: 7) var a = 13
rewritten by the compiler as
let $a = Clamping(initialValue: 13, min: 1, max: 7)
var a: Int {
get { $a.value }
set { $a.value = newValue }
}
Essentially extend the current logic which looks for init(initialValue: T) to also look for init(initialValue: T, ... <other args from declaration>)