SE-0244: Opaque Result Types

Indeed, this is pretty much what opaque types boil down to, is the ability for a function to "output" generic parameters in addition to taking them as inputs. Another way we could conceivably notate this is by putting the output parameters after the ->, as a number of people suggested:

makeFoo() -> <F: Foo> F

The proposal tries to explain it, though the section about it is quite lengthy and I can see how it can be unclear. @Douglas_Gregor, maybe we should go over this section again and try to make it more to the point. @svanimpe's description is a good summary.

I understand the concern about searchability, and I checked—Google does a fine job providing relevant answers for swift some today. (There's a legitimate concern that having two somes could dilute the waters, I agree.) I however don't agree that this feature will remain obscure for long. The equivalent impl Trait feature in Rust is used pervasively; On Github I find 5,000 hits for impl Fn arguments and returns, 1,000 for impl Iterator<Item=...>, and 400 for impl Future alone. Although Swift uses type erasure for function types, obviating the first to some degree, we could deploy this feature for standard library collections as the proposal suggests, and we could well end up with protocol-oriented futures, key paths (and maybe even generic function objects like Rust's, since there are optimizations that enables that our current closure design makes difficult) in the future. Part of the goal of this feature is to make those sorts of libraries easier and more ergonomic to design and use.

As for "Huffman coding" the identifier, I have a couple other reasons I think going for something concise that reads well is a good idea. I'd really like to see this feature eventually extend to also allow generic arguments to be written as some Protocol, the same way that Rust lets you use impl Trait as an argument, since that will make writing a lot of simple generic functions clearer and easier. For this sugar to be worth using, it ought to be at least as concise and readable as the syntax it replaces, and a bulky, obscure keyword would kill that quickly. Furthermore, I also see a bit of a let vs var situation with regard to existential notation. @dabrahams and others have noted that protocol existentials in their full generality quickly become a rather obscure, complex feature, that doesn't necessarily deserve the pride of place it currently has in our type syntax (and that if anything, opaque types as provided by this feature are in fact closer to what you really want a good percentage of the time we currently tell people to use existentials). Rust eventually decided that making existentials undecorated was a bad idea and added the dyn keyword to encourage their use to be explicit. In previous discussions of existential syntax, Any or any seemed like the clear favorite as the modifier keyword for explicitly introducing an existential. Both linguistically, and in the spirit of fairness of not syntactically biasing one style over the other, Some or some strikes me as the corresponding modifier for specific opaque types.

14 Likes