Anonymous Structs

I don't find it a terribly convincing argument to say that we should only consider the best-case usage of a given language feature. It's worth considering worst-case usage as well, as well as the problems which might present themselves when a feature like this is used in a large and evolving codebase.

What I see this pitch, as well as the equality of functions thread where this pitch has come out of, is that it seems to be heavily shaped by how nice it would be for SwiftUI and for another FRP framework which is being discussed in the other thread. The risk I see here is that this feature could be over-fit for a specific use-case at the expense of others and at the expense of the clarity and readability of language as a whole.

I understand what you're saying with respect to the possibility that more than one callAsFunction requirement exists, but I strongly disagree that these issues exist in the same measure while the scope is limited to callAsFunctionRequirements. The big advantage I see in limiting the scope in this way is that when I see a protocol being used for an anonymous trailing closure, I can look at the protocol and immediately know with a high degree of certainty which protocol requirement is being instantiated by that anonymous closure. If it can be any of the requirements, including functions or variables (as in the case of the View.body requirement), then I as the developer have to mentally model the compiler's inference process to understand which one of these requirements is being instantiated. This places significantly more cognitive burden on the developer.

As you say, it's possible to have protocols with more than one callAsFunction requirement, but this is going to be significantly more niche than protocols with more than one requirement in general. Also in the case of protocols with a mix of callAsFunction requirements and other requirements, this limitation already lets you limit the possibilities to consider when trying to parse this type of code.

The other motivation I can see for this limitation is that it makes this feature a more incremental change in the language. As @Joe_Groff has described it, with the callAsFunction requirement, this feature is just essentially adding more power to closures. It would be possible to look at code using the feature, and it would look almost identical to current closure usage, with only one new concept to absorb. There's also no reason this limitation couldn't be relaxed in the future if it becomes obvious that broader inference would be useful. But it might be worth introducing the feature in a more limited way at first, and see how APIs evolve to react to the feature before introducing it in a way which is hyper-targeted to the APIs we have now.

The risk I see is that this feature has the potential to inject a lot of magic and cleverness into Swift code. Flexibility comes at a cost. For instance, I would like for Swift to avoid the type of situation you have in a Javascript codebase where someone has done something very clever with the object model, or for instance walking into a very esoteric Scala codebase. I think there's evidence in this thread that the feature as currently proposed is a step in that direction, based on the initial confusion this proposal was met with by some posters.

5 Likes