[swift-evolution] [Preemptive Proposal] Operator for Lenses

Brent Royal-Gordon brent at architechies.com
Thu Jan 14 19:30:16 CST 2016

> Could you please explain what a lens is/means? I only found [1], but quick skimming didn't reveal any lenses.
> [1] https://www.youtube.com/watch?v=estNbh2TF3E

In pure functional programming languages, where you can't mutate existing instances, a lens is a function which takes an instance and a new value for some field inside the instance—sometimes deep inside it—and returns a copy of the original instance with that new value in place. So, for instance, if you have a `User` type which has a `name` property:

	let nameLens = User.name
	let currentName = nameLens.get(originalUser)			// get the name from originalUser
	let modifiedUser = nameLens.set(originalUser, to: "Joe")	// return a copy of originalUser with name set to "Joe"

In functional programming, you can easily chain lenses together, so that you could create a lens for, say, `User.creditCards[0].billingAddress.houseNumber`—and the setter on that lens will actually take a house number and return a whole different `User` instance with that house number applied.

Now, Swift is a little different from a pure functional language. It doesn't have the limitation that functional languages do—it's perfectly fine to modify existing instances—so a Swift lens's setter would probably actually modify the existing instance. On the other hand, Swift often modifies an existing value inside a property instead of creating a whole new one, so the "setter" is better modeled as a read-modify-write operation:

	let nameLens = User.name
	let currentName = nameLens.get(originalUser)
	nameLens.modify(originalUser) { (inout name: String) in
		name = "Joe"

Finally, there's the question of how you should *access* a lens. `User.name`—that is, a lens that can be used with any instance of `User`—is good for some things, but you'd also like to be able to get a lens that's already bound to a particular instance.

Michael Henson is basically proposing syntaxes to retrieve a lens for a particular instance, but personally, I think this is putting the cart before the horse a bit. Right now, I'm personally more interested in finding out what a lens *is* in Swift. What can it do? How is it expressed? What can you use it for?

Brent Royal-Gordon

More information about the swift-evolution mailing list