SE-0253: Static callables

I haven't had much time to think about this, so I haven't read all the comments, but I'll jot down a few more thoughts:

  • One advantage of having a dedicated name for call functions (whether call(…), func _(…), or whatever) is that there is only one thing the compiler has to look up when you say foo(). If the functions can be arbitrarily named, the compiler has to crawl through all members of the type, or we have to start keeping a separate index. (The latter's not that bad but it increases the complexity of the compiler in other ways.)

  • I don't think this is a universally held opinion, but personally I think being able to say obj.foo (or even obj.foo(of:)) as shorthand for { obj.foo($0) } has worked out really poorly, especially when in an escaping context. For classes, it captures the self value in a way that's non-obvious, making it harder to get a sense of your object graph when reading code. For value types, it doesn't work with mutating operations. The version that only has the base name breaks when other overloads of foo get defined. (This shows up the most with init.) So I'd much rather end up in a space with the "implicit conversion" (wrap in a closure) than a space where foo.call becomes common, and without that I think writing the explicit { foo($0) } is fine.

  • I still really want to see information about the ABI of call declarations, or an explicit acknowledgement that call will not be supported when deploying against a Swift 5.0 runtime (along with a commitment to verifying that in the compiler).

9 Likes