[swift-evolution] [Pitch] KeyPath based map, flatMap, filter

Elviro Rocca retired.hunter.djura at gmail.com
Mon Jul 17 02:16:40 CDT 2017

Subscripts in Swift in fact have always looked to me like a way to make objects "callable", where you use brackets instead of parentheses: the difference of course is the fact that, when used point-free, the object will be considered an instance and not a function.

In this sense we could theoretically make a KeyPath callable by adding subscripts; consider the following code:

extension KeyPath {
	subscript (get root: Root) -> Value {
		return root[keyPath: self]

struct Person {
	var firstName: String
	var lastName: String

let x = Person.init(firstName: "Foo", lastName: "Bar")

let foo = (\Person.firstName)[get: x] /// "Foo"

This is valid Swift code (Swift 4.0 snapshot 2017-07-13). In theory a possible evolution of this could be referencing the subscript function in a point-free way like we can already do with regular functions:

let callable1 = (\Person.firstName)[get:] /// this won't compile

For the setter part, because the other half of a KeyPath is essentially a function of type (Value, inout Root) -> (), we could theoretically considering this kind of subscript function:

extension KeyPath {
	subscript (set value: Value, on root: inout Root) -> () { /// this won't compile
		root[keyPath: self] = value
		return ()

let callable2 = (\Person.firstName)[set:,on:] /// this won't compile

But we cannot write subscripts with inout parameters. I actually find the subscript path a very interesting one to consider, but there's still a lot of machinery that's missing.

I would prefer two standardized prefix operators - for extracting the "(Root) -> Value" and the "(Value,inout Root) -> ()" parts of a KeyPath - to be added to the standard library. This is exactly the case where custom operators make sense: repeated operations that should be expressed with minimum code noise.


> Il giorno 16 lug 2017, alle ore 18:34, Benjamin Herzog via swift-evolution <swift-evolution at swift.org> ha scritto:
> If it would be possible to make objects callable, wouldn't that also go
> in the same direction as subscripts currently? One could also implement
> it with the syntax for callable functions (in this case anonymous -
> without a name). Instead of this:
> subscript(index: Int) -> T
> we could also write
> func (_ index: Int) -> T
> On the call side it would change from this:
> list[3] to list(3)
> I know that it's not necessary and not even better readable, but it goes
> in the same direction in my opinion and is worth considering. What do
> you think?
> ______________________
> Benjamin Herzog
> On Wed, Jul 12, 2017, at 10:21 PM, Dave Abrahams via swift-evolution
> wrote:
>> on Tue Jul 11 2017, Robert Bennett <rltbennett-AT-icloud.com> wrote:
>>> Just realized that even inout functions don’t let you do
>>> member(object) = value. 
>> The other difference is that an inout function can't be used to get a
>> member from an immutable value, whereas a keypath/subscript/property
>> access can.
>> -- 
>> -Dave
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

More information about the swift-evolution mailing list