<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">I am excited by the general direction but I have some concerns about the scope of the design at this time; specifically, it seems like it would benefit a lot from having some flexible-and-efficient way for behaviors to “reach upward” back into their container from within their custom methods (without forcing the caller to pass-in the container to each such call, of course).</div><div class=""><br class=""></div><div class="">I took a stab at mocking up one of the behaviors I’d like to be able to write and hit a lot of roadblocks due to the above; I’ve included it below with some commentary. </div><div class=""><br class=""></div><div class="">Even though this is perhaps a rather extreme/niche behavior to want to implement, I think the issues it encountered are actually general enough that other useful behaviors will also encounter them under the proposal as sketched.</div><div class=""><br class=""></div><div class="">Here’s the sample use, starting with motivation.</div><div class=""><br class=""></div><div class="">For some APIs — e.g. CoreBluetooth — you often wind up with highly-stateful objects that receive callbacks on a specific queue, and typically also do their state-maintenance while on that same queue; these objects typically also have a “public API” with methods that are only meant for use while off the queue (e.g. from the main queue, to update the UI…).</div><div class=""><br class=""></div><div class="">You thus wind up with each method-and-property pretty clearly being one and only one of these:</div><div class=""><br class=""></div><div class="">- “on-queue”, e.g. *only* meant for use while on the object’s queue</div><div class="">- “off-queue”, e.g. *only* meant for use while off the object’s queue</div><div class=""><br class=""></div><div class="">…with concurrency-and-synchronization logic essentially amounting to only calling / using each method-and-property while appropriately on/off queue.</div><div class=""><br class=""></div><div class="">For a concrete example, for an implementer of CBCentralManagerDelegate:</div><div class=""><br class=""></div><div class="">- all the CBCentralManagerDelegate methods are "on-queue"</div><div class="">- all the BT-state-management methods (called in reaction to BT events) are also “on-queue”</div><div class="">- the public methods (e.g. for UI use, or for asking the object to do stuff) are “off-queue”</div><div class="">- some of the basic properties (status, is-peripheral-foo-connected?) are oddballs, and get:</div><div class=""> - private backing properties for use/update while on-queue</div><div class=""> - public off-queue accessors that do a dispatch_sync, read the backing property, and return it</div><div class=""><br class=""></div><div class="">…and so on.</div><div class=""><br class=""></div><div class="">This can all be handled today "by hand” — it just requires being careful — but it’d be nice to have a custom behavior that would streamline both the implementation of on/off queue access for properties, and make each site-of-use more self-documenting/self-verifying vis-a-vis on/off-queue status.</div><div class=""><br class=""></div><div class="">Here’s my best attempt (issues flagged in ALL-CAPS):</div><div class=""><br class=""></div><div class="">/// Object assumed to have private queue it uses for synchronization.</div><div class="">protocol PrivateQueueOwner : class {</div><div class=""><br class=""></div><div class=""> // we don’t want to leak the actual queue to the wider world,</div><div class=""> // so we have to bubble these up to the public API:</div><div class=""> func dispatchSync<R>(@noescape action: () -> R) -> R</div><div class=""> func dispatchBarrierSync<R>(@noescape action: () -> R) -> R</div><div class=""> func dispatchAsync(action: () -> ())</div><div class=""> func dispatchBarrierAsync(action: () -> ())</div><div class=""><br class=""></div><div class=""> // we assume we are managing our queues s.t. we can</div><div class=""> // actually get the below to work reliably:</div><div class=""> func isOnPrivateQueue() -> Bool</div><div class=""><br class=""></div><div class="">}</div><div class=""><br class=""></div><div class="">/// Behavior used to enforce a particular use-pattern around</div><div class="">/// a property of an object that uses a private queue for synchronization:</div><div class="">struct QueueAccess<Value> {</div><div class=""> var value: Value</div><div class=""> </div><div class=""> // THIS PART IS ONLY-KINDA OK:</div><div class=""> subscript<Container:PrivateQueueOwner>(varIn container: Container> {</div><div class=""> get {</div><div class=""> if container.isOnPrivateQueue() {</div><div class=""> return self.value</div><div class=""> } else {</div><div class=""> return self.container.dispatchSync() {</div><div class=""> return self.value</div><div class=""> // ^ DOES THIS ACTUALLY WORK AS I’D WANT, IF I AM A STRUCT?</div><div class=""> }</div><div class=""> }</div><div class=""> }</div><div class=""> set {</div><div class=""> if container.isOnPrivateQueue() { </div><div class=""> self.value = newValue</div><div class=""> } else {</div><div class=""> container.dispatchBarrierAsync() {</div><div class=""> self.value = newValue</div><div class=""> // ^ DOES THIS ACTUALLY WORK AS I’D WANT, IF I AM A STRUCT?</div><div class=""> }</div><div class=""> }</div><div class=""> }</div><div class=""> }</div><div class=""><br class=""></div><div class=""> // EVERYTHING FROM HERE ON DOWN IS MOSTLY PROBLEMATIC:</div><div class=""><br class=""></div><div class=""><div class=""> func onQueueUpdate(newValue: Value) { </div><div class=""> assert(self.container.isOnPrivateQueue()) // <- HOW?</div><div class=""> self.value = newValue</div><div class=""> }</div><div class=""> </div><div class=""> func offQueueUpdate(newValue: Value) {</div><div class=""> assert(self.container.isOffPrivateQueue()) // <- HOW?</div><div class=""> self.container.dispatchBarrierAsync() { // <- HOW?</div><div class=""> self.value = newValue</div><div class=""> // ^ DOES THIS EVEN WORK IF I AM A STRUCT? </div><div class=""> }</div><div class=""> }</div><div class=""><br class=""></div><div class=""> func offQueueAccess() -> Value {</div><div class=""> assert(self.container.isOffPrivateQueue()) // <- HOW?</div><div class=""> return self.container.dispatchSync() { // <- HOW?</div><div class=""> return self.value</div><div class=""> }</div><div class=""> }</div><div class=""><br class=""></div><div class=""> func onQueueAcccess() -> Value {</div><div class=""> assert(self.container.isOnPrivateQueue()) // <- HOW?</div><div class=""> return self.value</div><div class=""> }</div></div><div class=""><br class=""></div><div class=""><div class=""> func offQueueAccess<R>(@noescape transform: (Value) -> R) -> R {</div><div class=""> assert(self.container.isOffPrivateQueue()) // <- HOW?</div><div class=""> return self.container.dispatchSync() { // <- HOW?</div><div class=""> return transform(self.value)</div><div class=""> }</div><div class=""> }</div><div class=""><br class=""></div><div class=""> func onQueueAcccess<R>(@noescape transform: (Value) -> R) -> R {</div><div class=""> assert(self.container.isOnPrivateQueue()) // <- HOW?</div><div class=""> return transform(self.value)</div><div class=""> }</div></div><div class=""><br class=""></div><div class="">}</div><div class=""><br class=""></div><div class="">….which if it was implementable, would wind up used like so:</div><div class=""><br class=""></div><div class="">public class BTCentralManagerController : NSObject, CBCentralManagerDelegate, PrivateQueueOwner {</div><div class=""><br class=""></div><div class=""> internal lazy var centralManager: CBCentralManager = CBCentralManager(</div><div class=""> delegate: self, </div><div class=""> queue: self.privateQueue, </div><div class=""> options: self.centralManagerOptions()</div><div class=""> )</div><div class=""> </div><div class=""> private let privateQueue: dispatch_queue_t </div><div class=""> </div><div class=""> public private(set) var (queueAccess) centralManagerState: CBCentralManagerState = .Unknown</div><div class=""> internal private(set) var (queueAccess) peripheralControllers: [NSUUID:BTPeripheralController] = [:]</div><div class=""> </div><div class=""> // internal API sample:</div><div class=""><br class=""></div><div class=""> func centralManagerDidUpdateState(_ central: CBCentralManager) {</div><div class=""> self.centralManagerState.queueAccess.onQueueUpdate(central.state)</div><div class=""> }</div><div class=""> </div><div class=""> // public API sample</div><div class=""><br class=""></div><div class=""> public func peripheralControllerForUUID(uuid: NSUUID) -> BTPeripheralController? {</div><div class=""> // this is an explicitly “off-queue” method:</div><div class=""> self.currentState.queueAccess.offQueueAccess() {</div><div class=""> return $0[uuid]</div><div class=""> }</div><div class=""> }</div><div class=""><br class=""></div><div class="">}</div><div class=""><br class=""></div><div class="">…giving us:</div><div class=""><br class=""></div><div class="">- safe defaults for attempted direct-property access</div><div class="">- self-dcoumenting/self-validating customized getters-and-setters for all internal-use scenarios</div><div class=""><br class=""></div><div class="">But, as the # of ALL-CAPS comments should indicate, this behavior seems *well beyond* what the proposal can provide in a natural way (e.g. we can get closer by passing-in the container to each method, but that’s a lot less natural and a lot clunkier).</div><div class=""> </div><div class="">Moreover, even if the “ability to access the container” were to be addressed, I also don’t like having to use a protocol like `PrivateQueueOwner` to make my `queueAccess` behavior re-usable; at least at present, adopted-protocol visibility is the same visibility as the type itself, so that e.g. if a public class conforms to `PrivateQueueOwner` then all the methods in `PrivateQueueOwner` are also public.</div><div class=""><br class=""></div><div class="">This is undesirable, as although I’d want such classes to be public, I wouldn’t want such low-level implementation details to be part of their public API.</div><div class=""><br class=""></div><div class="">Ideally, rather than forcing the container to adopt a protocol, I could instead do something *more* like this:</div><div class=""><br class=""></div><div class=""><div class="">public class BTCentralManagerController : NSObject, CBCentralManagerDelegate {</div></div><div class=""><br class=""></div><div class=""><div class=""> private let privateQueue: dispatch_queue_t </div></div><div class=""> </div><div class=""> // configures `queueAccess` behavior to use `self.privateQueue` (with on-queue check also as-specified)</div><div class=""> // ...note that if this becomes possible, the syntax might need to change, b/c the below is not very readable!</div><div class=""> public private(set) var (queueAccess(queue: `self.privateQueue`, onQueue: `self.isOnPrivateQueue()`)) currentState: CBCentralManagerState = .Unknown</div><div class=""> internal private(set) var (queueAccess(queue: `self.privateQueue`, onQueue: `self.isOnPrivateQueue()`)) peripheralControllers: [NSUUID:BTPeripheralController] = [:]</div><div class=""><br class=""></div><div class="">}</div><div class=""><br class=""></div><div class="">// which somehow interacts with a declaration like this:</div><div class="">struct QueueAccess<Value> {</div><div class=""><br class=""></div><div class=""> var value: Value</div><div class=""><br class=""></div><div class=""> // declaration stating we expect a `queue` expression during configuration, with the </div><div class=""> // following type (and the accessor automagically-synthesized via compiler magic)</div><div class=""> container var queue: dispatch_queue_t { get }</div><div class=""><br class=""></div><div class=""> // declaration stating we expect an `onQueue` expression during configuration, with the </div><div class=""> // following type (and the implementation automagically-synthesized via compiler magic)</div><div class=""> container func onQueue() -> Bool</div><div class=""><br class=""></div><div class=""> func onQueueUpdate(newValue: Value) { </div><div class=""> assert(self.onQueue()) </div><div class=""> self.value = newValue</div><div class=""> }</div><div class=""> </div><div class=""> func offQueueUpdate(newValue: Value) {</div><div class=""> assert(!self.onQueue())</div><div class=""> dispatch_barrier_async(self.queue) {</div><div class=""> self.value = newValue</div><div class=""> // ^ NOTE: this may still be a problem for struct-based behaviors...?</div><div class=""> }</div><div class=""> }</div><div class=""> </div><div class=""> // etc...</div><div class=""> </div><div class="">}</div><div class=""><br class=""></div><div class="">…which, if possible, would obviously make behaviors a lot more specialized than they are under the current proposal (e.g. they would seemingly need a lot of specialized help from the compiler to be able to access those variables without either creating a strong reference to the container or wasting a lot of space with redundant stored properties, and might be their own specialized type, rather than an otherwise-vanilla struct-or-class as per the current proposal). </div><div class=""><br class=""></div><div class="">But, if the above were possible, the behaviors would be a *lot* more re-usable, and it’d be unnecessary to have the container adopt a particular protocol.</div><div class=""><br class=""></div><div class="">Note also that even if the “unwanted API pollution” issue were resolved — e.g. by making it possible to somehow privately-adopt a protocol, or equivalent — there’d still be the issue of getting efficient access to the container to address, if these use cases are to be supported.</div><div class=""><br class=""></div><div class="">So that’s my reaction; if you read it this far, thanks for your attention.</div><div class=""><br class=""></div><div class="">I’d *completely* understand if the reaction here is simply that such uses are out-of-scope for this proposal; that seems perfectly reasonable!</div><div class=""><br class=""></div><div class="">But keep in mind, the general issue of reaching-up from custom methods of behaviors can show up in simpler contexts:</div><div class=""><br class=""></div><div class="">// convenience logic:</div><div class="">private extension UIViewController {</div><div class=""><br class=""></div><div class=""> func viewHasEnteredWindow() -> Bool {</div><div class=""> return self.viewIfLoaded()?.window != nil ?? false</div><div class=""> }</div><div class="">}</div><div class=""><br class=""></div><div class="">// custom behavior:</div><div class="">struct MustSetBeforeVisibility<Value> {</div><div class=""> value: Value?</div><div class=""> </div><div class=""> // THIS PART OK:</div><div class=""> subscript<Container:UIViewController>(varIn container: Container> -> Value? {</div><div class=""> get {</div><div class=""> if container.viewHasEnteredWindow() {</div><div class=""> guard let v = self.value else { </div><div class=""> fatalError(“Should’ve set property \(self) by now, b/c our VC’s view is in the window (vc: \(container))”)</div><div class=""> }</div><div class=""> return v</div><div class=""> } else {</div><div class=""> return self.value // perfectly-cromulent to be unset at this point in lifecycle</div><div class=""> }</div><div class=""> }</div><div class=""> set {</div><div class=""> if !container.viewHasEnteredWindow() {</div><div class=""> self.value = newValue</div><div class=""> } else {</div><div class=""> fatalError(“Not meant to be set after we have become potentially-visible!")</div><div class=""> }</div><div class=""> }</div><div class=""> }</div><div class=""><br class=""></div><div class=""> // HOW TO DO THIS PART:</div><div class=""> /// non-optional convenience accessor; only meant for use once our view has </div><div class=""> /// become potentially-visible</div><div class=""> func direct() -> Value {</div><div class=""> if !container.viewHasEnteredWindow() { // <- HOW?</div><div class=""> fatalError(“Trying to do direct-access on \(self) too soon!")</div><div class=""> } else if let v = self.value {</div><div class=""> return v</div><div class=""> } else {</div><div class=""> fatalError(“Trying to do direct-access, but never set the value for \(self) appropriately!")</div><div class=""> }</div><div class=""> }</div><div class=""><br class=""></div><div class="">}</div><div class=""><br class=""></div><div class="">…which is basically another take on a “smarter” implicitly-unwrapped-optional. You don’t *need* a function like `direct()`, but you might want it, and it might be nice to be able to differentiate “using too soon” and “forgot to set the value”.</div><div class=""><br class=""></div><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 17, 2015, at 11:37 AM, Joe Groff via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Hi everyone. Chris stole my thunder already—yeah, I've been working on a design for allowing properties to be extended with user-defined <strike class="">delegates^W</strike> behaviors. Here's a draft proposal that I'd like to open up for broader discussion. Thanks for taking a look!<div class=""><br class=""></div><div class="">-Joe</div><div class=""><br class=""></div><div class=""><a href="https://gist.github.com/jckarter/f3d392cf183c6b2b2ac3" class="">https://gist.github.com/jckarter/f3d392cf183c6b2b2ac3</a></div><div class=""><br class=""></div><div class=""><div id="generated-toc" class="generate_from_h1 generate_for_page" style="position: fixed; max-height: 90%; width: 250px; overflow-x: hidden; overflow-y: auto; right: 20px; bottom: -972px; font-size: 1.1em; line-height: 1.2em; background-color: rgba(0, 0, 0, 0.8); color: rgb(200, 200, 200); padding: 10px 30px 20px 20px; border-top-left-radius: 10px; border-top-right-radius: 10px; border-bottom-right-radius: 10px; border-bottom-left-radius: 10px; transition: all 0.3s ease-out; -webkit-transition: all 0.3s ease-out; word-wrap: break-word; z-index: 101; outline: 0px; border: 0px; font-family: -webkit-standard;"><ul style="padding-left: 0px; margin-left: 10px;" class=""><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><ul style="padding-left: 0px; margin-left: 10px;" class=""><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><ul style="padding-left: 0px; margin-left: 10px;" class=""><li class="missing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><ul style="padding-left: 0px; margin-top: 0px; margin-left: 10px;" class=""><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#lazy" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Lazy</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#memoization" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Memoization</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#delayedinitialization" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Delayed Initialization</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#resettableproperties" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Resettable properties</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#synchronizedpropertyaccess" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Synchronized Property Access</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#nscopying" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">NSCopying</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#referencingpropertieswithpointers" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Referencing Properties with Pointers</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#propertyobservers" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Property Observers</a></li></ul></li></ul></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#detaileddesign" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Detailed design</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#impactonexistingcode" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Impact on existing code</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#alternativesconsideredtoconsider" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Alternatives considered/to consider</a><ul style="padding-left: 0px; margin-left: 10px;" class=""><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#declarationsyntax" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Declaration syntax</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#syntaxforaccessingthebackingproperty" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Syntax for accessing the backing property</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#definingbehaviorrequirementsusingaprotocol" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Defining behavior requirements using a protocol</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#abehaviordeclaration" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">A behavior declaration</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#namingconventionforbehaviors" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Naming convention for behaviors</a></li></ul></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#todo" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">TODO</a></li></ul></li></ul></div><div class=""><br class=""></div></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=9EwXyNl81W9TT3yZ17PL28-2Be7Ks-2FXLjqa0dZcsddi5b5y8G-2Fn3lLXOA3ZQqrSAmMqa0E1zXRJ5C4Sr9PK9V4pHz8Usi2GRRz1vtd8KA8kJnpkjqi4NGP4iMJtqRFuXjwZcHo8nc17yhkBHMeSkvNEz70VPEs4WVN-2BvDoa2AzMEifTBERp2OpJI-2FSo9vyN8SAdqm1K506JwSRDhErJLa3BMzYAnpiUOjVW4GQeV62XO4-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;" class="">
</div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>