New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SR-3639] Surprising meaning of anonymous closure parameters if not all are used #46224
Comments
Comment by David Friberg (JIRA) In a closure expression, the parameter type(s) will be inferred from context. In your inline closure examples, the type of the shorthand argument names will be inferred from the expected function type; let arr = [1,2,3,4,5]
let sum = arr.reduce(0) { $0.0 + $0.1 }
let count = arr.reduce(0) { $0.0 + 1 } Now, you could explicitly ignore "trailing" arguments when using named arguments (as per below), but for a single supplied let arr = [1,2,3,4,5]
let sum = arr.reduce(0) { a, b in a + b }
let count = arr.reduce(0) { a, _ in a + 1 } Finally note that preceding arguments to single supplied shorthand argument may be omitted for use (although available and with an inferred type) in a closure, but this does not hold for "trailing" ones. let arr = [(1, 1, 1), (2, 2, 2)]
arr.forEach { print($2) } // OK, $0 and $1 available but not used
arr.forEach { print($1) } // error, "trailing" third argument implicitly omitted With this discussion in mind, I believe an improvement such as this one would introduce ambiguity w.r.t. inferring shorthand argument types based on implementation details in the body of the closure vs from the expected function type. |
Comment by Raphael (JIRA) > Since you may not implicitly ignore the argument of a closure [...] by providing only $0, this must be inferred as a tuple. I guess this is where I'm not following. What prevents us from fixing the meaning of |
Comment by David Friberg (JIRA) Ah, I didn't realize you were talking about changing the default behaviour rather than implementing even more elaborate type inference. I believe the former will in fact be implemented in Swift 4, following the Swift evolution proposal SE-0110: "Swift's type system should properly distinguish between functions that take one tuple argument, and functions that take multiple arguments." This will lead to only e.g. the non-tuple shorthand arguments ( let count = arr.reduce { $0 + 1 } will still not compile in Swift 4; due to the omitted out 2nd argument. I.e., you will most likely still need to explicitly use named arguments to omit trailing ones, e.g. |
Comment by Raphael (JIRA) Thanks for the reference; it seems indeed that SE-0110 has the potential to simplify if not solve this issue here. (And it is, indeed, a requirement – I can see that now.) Is there a deeper reason for disallowing the omission of trailing anonymous arguments? That is to say, are you saying "I guess it will still be invalid code" or "I should still be invalid code because X"? |
Comment by David Friberg (JIRA) I can only answer that with the former; if the the current syntactic rules in this context persist into Swift 4, I guess the example above will still be syntactically invalid due to the explicitly omitted trailing argument (which is currently not allowed). I don't know the rationale for this rule, however; possibly it exists so that there's a clear-cut non-ambiguity between the choice of single-tuple or multiple parameters when using shorthand arguments, a differentiation that will naturally not be needed with the implementation of SE-0110. This is just me speculating however, so for you last question it would be interesting to get some feedback from the Swift team. |
The "deeper reason" was just that (a long time ago) we didn't want you to forget that there were more arguments. It's been mildly unpopular since Swift 1, and we could consider removing that restriction. The diagnostic is better on master:
|
Comment by Raphael (JIRA) I think a warning "you did not use implicit parameter And yes, that error message is a lot better. |
Comment by Raphael (JIRA) SE-0110 was deferred. |
Additional Detail from JIRA
md5: ce9ce5fe8b89bc9d52742e7b3f4fd47f
relates to:
Issue Description:
Compare these two expressions using
reduce
:The second one does not compile because you can not add
(Int,Int)
andInt
. Which is true, but it is a surprising error: the natural expectation is that$0
and$1
retain the same semantics even though only one of them is used.The text was updated successfully, but these errors were encountered: