[swift-evolution] [Review] SE-0194: Derived Collection of Enum Cases

Brent Royal-Gordon brent at architechies.com
Thu Jan 11 23:42:29 CST 2018

> On Jan 11, 2018, at 4:21 PM, Paul Cantrell <cantrell at pobox.com> wrote:
> This raises a question related to Chris’s: what is the utility of having Limb conform to a protocol instead of just providing allValues ad hoc? Does CaseEnumerable / ValueEnumerable serve any purpose other than triggering special behavior in the compiler? Would the protocol ever be used as the type of something in code?
> My answers, admittedly weak ones, are: (1) conventions are nice and consistency is nice, and (2) you never know how an abstraction might be used, but you do know that people will be angry when it should fit but doesn’t. I can’t come up with a more compelling or specific argument than those.

Here's a place where you might want to use the protocol: Suppose you're writing a table view data source that displays editable controls for a form. You support several different types of controls, one of which is a list of choices for a picker controller.

	enum Control<Value> {
		case textField
		case picker(choices: [Value])
		func makeView() -> UIView { … }
		subscript(valueOf view: UIView) -> Value { get { … } set { … } }

Presumably you end up writing a schema which looks something like:

	formDataSource = FormDataSource(value: person)
	formDataSource.fields = [
		Section(title: nil, fields: [
			Field(title: "Name", keyPath: \.name, control: .textField),
			Field(title: "Gender", keyPath: \.gender, control: . picker(choices: Array(Gender.allValues))),
	tableView.dataSource = formDataSource

The `Array(Gender.allValues)` here is clutter; it'd be nice if we didn't have to write it explicitly. After all, if you're choosing a value of something you know is an enum, it's sensible to assume that you want to choose from all values if it doesn't specify anything more specific. If `ValueEnumerable` is a formalized protocol, you can do that with a constrained extension:

	extension Control where Value: ValueEnumerable {
		static var picker: Control {
			return .picker(choices: Array(Value.allValues))

And now you just need to write:

			Field(title: "Gender", keyPath: \.gender, control: . picker)

Basically, having `ValueEnumerable` be a formal protocol means we can extend this small automatic behavior into larger automatic behaviors. I can imagine, for instance, building a fuzzer which, given a list of `WritableKeyPath`s whose types are all `ValueEnumerable`, automatically generates random instances of a type and feeds them into a test function. If we get read-write reflection, we might be able to do this automatically and recursively. That'd be pretty cool.

Brent Royal-Gordon

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

More information about the swift-evolution mailing list