[swift-evolution] Property Selectors

Andrew Thompson mrwerdo331 at me.com
Sun Mar 19 20:25:44 CDT 2017


Opps, should have sent this to the mailing list….

That sounds pretty good. 😊 I find the response from the community to this proposal to be pretty cool.

While reading some of the discussion around your proposal, I’ve seen requests where people are wanting to retrieve the list of an object’s properties. I think this is an interesting idea to explore, particularly if it was possible to generalise about all of the properties stored on an object.

For example, consider the following:

We have a protocol, JSONEncodable, and a bunch of types that conform to it, namely `Int`, `String`, and `Data`.

	protocol JSONEncodable {
		func encode() -> String
	}

	extension Int {
		func encode() -> String { … }
	}
	
	// similarly for String and Data.

A very common scenario that occurs is composing a type where all properties conform to a particular protocol, for example:

	struct Person {
		var age: Int
		var name: String
		var identifier: Data
	}

Now, we want to have `Person` conform to `JSONEncodable`, so we could just implement the encode method ourselves:

	extension Person: JSONEncodable {
		func encode() -> String {
			return age.encode() + name.encode() + identifier.encode()
		}
	}

But this seems a little bit repetitive, what we really want is for the library author to declare the following:

	For every type T whose properties conform to protocol P, we can derive a free conformance to protocol P for type T.

Applying this, we get the following code:

	extension JSONEncodable where Self.InstanceProperties: JSONEncodable {
		func encode() -> String {
			let properties = Metatype<Self>.properties
			var output = “”
			for p in properties {
				output += p.read(self).encode()
			}
			return output
		}
	}

Now all a user needs to do is say that want to conform to the protocol:

	struct Person: JSONEncodable {
		var age: Int
		var name: String
		var identifier: Data
	}

Cheers,
- Andrew

> On 18 Mar 2017, at 6:08 am, Joe Groff <jgroff at apple.com> wrote:
> 
>> 
>> On Mar 14, 2017, at 1:02 AM, Andrew Thompson via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> Hello Swift Evolution Community,
>> 
>> I’ve been thinking about a new language feature that would allow properties to be first class citizens. The basic idea is as follows:
>> 
>> 	let x: PropertySelector<UIView, CGFloat> = #property(UIView.frame.origin.x)
>> 	let view: UIView = …
>> 	view.frame.origin.x = 20
>> 	x.read(view) // returns 20
>> 	x.write(view, value: 9091)
>> 	view.frame.origin.x // now 9091
>> 
>> This is a trivial example, but now we can do more interesting things in our code. For example, we can animate any property on a view (that is documented to be animatable of course):
>> 
>> 	func animate(view: UIView, property: PropertySelector<UIView, CGFloat>, amount: Int) {
>> 		let originalValue = property.read(view)
>> 		func generateKeyFrames() {
>> 			let step = 1.0 / Double(amount)
>> 			for i in 0..<amount {
>> 				let newValue = originalValue + CGFloat(i)
>> 				let time = Double(i) / Double(amount)
>> 				UIView.addKeyframe(withRelativeStartTime: time,
>> 								  relativeDuration: step,
>> 								  animations: { property.write(view, value: newValue) }
>> 				)
>> 			}
>> 		}
>> 		
>> 		UIView.animateKeyframes(withDuration: 1.0,
>> 							   delay: 0,
>> 							   options: [],
>> 							   animations: generateKeyFrames,
>> 							   completion: nil)
>> 	}
>> 
>> 	let myView: UIView = …
>> 	myView.frame = CGRect(x: 20, y: 100, width: 99, height: 120)
>> 
>> 	// once this completes, myView.frame.origin.x == 120
>> 	animate(view: myView, property: #property(UIView.frame.origin.x), amount: 100)
>> 	
>> 	// once this completes, myView.frame.size.width == 198
>> 	animate(view: myView, property: #property(UIView.frame.size.width), amount: 99)
>> 
>> I think this would be a pretty neat feature to have, what do you think?
> 
> We agree! How does this sound:
> 
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170313/033998.html <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170313/033998.html>
> 
> -Joe

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170320/ac0e11d7/attachment.html>


More information about the swift-evolution mailing list