If you choose to make things inlinable and you're ABI stable, that is. Which very few libraries need to be. The standard library is a pretty rare case in this regard – it's a highly generic, highly performance-sensitive library, yet needs to be ABI stable. This really is quite a niche set of requirements.
I think there's some confusion from the fact that the motivating example came from the standard library. Most libraries (or non-library code in large code bases maintained by many people) either won't be ABI stable, or will be able to make their types resilient, and so can choose to inline and still use this feature. Under those circumstances, this feature gives you a big win in terms of source stability, in that you can swap out the old type for new without worrying about your callers having hard-coded the type on their side.
Even with the standard library being ABI stable, there would still be wins for users, not authors, of the std lib.
Take the LazyCompactMapCollection
example. Suppose you were writing something like the luhn algorithm on credit card numbers. For one step you have a string with digits and spaces and you want to turn it into a collection of actual digits, lazily. So you write a function for it:
func digits(ccnum: String) -> ??? {
return ccnum.lazy.compactMap {
Int(String($0))
}
}
What goes into ???
is the somewhat monstrous LazyMapCollection<LazyFilterCollection<LazyMapCollection<String, Int?>>, Int>
. To figure that out, you have to assign the value to variable and right-click it, then cut and paste what you find (assuming you're using Xcode... if not, good luck!). And if you composed it with more lazy methods, then it gets really ridiculous. Much nicer to make it opaque Collection where _.Element == Character
. If that's already what all the lazy methods return, all the better to guide you towards that.
If the standard library were to have had this from the beginning, it wouldn't even need to expose these different lazy types from map
, filter
etc. They would still need to be @inlinable internal
, so still in the ABI and not changeable after the fact, but users wouldn't have to know about their existence and they wouldn't need to appear in the documentation. That's a big simplification for new users unfamiliar with the fact that these different types don't matter for most purposes. Making that change now would be source breaking, so probably not worth it at this point, but would have been nice if we'd done it from the start.
But if you aren't ABI stable, you get an even bigger win! You can change lazy.compactMap
to return a completely different type, like SE-222 suggested, and you no longer break source when you do. This would have been huge during the development of the std lib prior to ABI stability, and I'm pretty certain it will be huge for the many libraries and codebases that exist today and want to increase their use of generics over time without breaking source whenever they need to refactor. Libraries like NIO, or many libraries found in the compatibility suite today, could certainly benefit from this.