Skip to content
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-4745] for (index, (a, b)) in dict.enumerated() produces an error #47322

Closed
palimondo mannequin opened this issue Apr 30, 2017 · 12 comments
Closed

[SR-4745] for (index, (a, b)) in dict.enumerated() produces an error #47322

palimondo mannequin opened this issue Apr 30, 2017 · 12 comments
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself type checker Area → compiler: Semantic analysis

Comments

@palimondo
Copy link
Mannequin

palimondo mannequin commented Apr 30, 2017

Previous ID SR-4745
Radar None
Original Reporter @palimondo
Type Bug
Status Resolved
Resolution Duplicate

Attachment: Download

Environment

Apple Swift version 3.1 (swiftlang-802.0.51 clang-802.0.41)
Target: x86_64-apple-macosx10.9

Additional Detail from JIRA
Votes 1
Component/s Compiler
Labels Bug, TypeChecker
Assignee @xedin
Priority Medium

md5: 3cf8b249d7223d158ce1e39c4c03487e

duplicates:

  • SR-2672 Implement tuple conversion

relates to:

  • SR-4738 Can not decompose nested tuple in closure arguments

Issue Description:

let someDict = ["one" : 1, "two" : 2]

for (index, (a, b)) in someDict.enumerated() {} // error

//for (index, (key: a, value: b)) in someDict.enumerated() {} // works

produces

error: cannot express tuple conversion '(offset: Int, element: (key: String, value: Int))' to '(Int, (String, Int))'
for (index, (a, b)) in someDict.enumerated() {
                    ^
     offset:  element:  key:  value: 
@palimondo
Copy link
Mannequin Author

palimondo mannequin commented Apr 30, 2017

@belkadan
Copy link
Contributor

belkadan commented May 2, 2017

Another case of inconsistent tuple conversions. cc @slavapestov, @rudkx

@natecook1000
Copy link
Member

It looks like Swift 4 doesn't allow even the simple case of matching count/element on an enumerated array—is that the intended behavior?

let a = [1, 2, 3, 4, 5]
let b = a.enumerated().map { (count, element) in "\(count): \(element)" }
// The error message is also unhelpful:
// error: cannot convert value of type 'String' to closure result type '_'

@belkadan
Copy link
Contributor

belkadan commented May 3, 2017

Yes, that one's correct. Closure arguments are not pattern matches. @xedin is working on improving this particular issue.

@palimondo
Copy link
Mannequin Author

palimondo mannequin commented May 4, 2017

@natecook1000, it seems like what you describe is even stricter than what's reported in SR-4738?

@xedin
Copy link
Member

xedin commented May 10, 2017

@natecook1000 Your example is related to SR-4738 and it's going to produce following diagnostic:

<REPL Input>:1:30: error: closure tuple parameter '(offset: Int, element: Int)' does not support destructuring
let b = a.enumerated().map { (count, element) in "\(count): \(element)" }
                             ^~~~~~~~~~~~~~~~
                             (arg) -> <#Result#> let (count, element) = arg; return

But `for` loop diagnostics might require some more work though.

@belkadan
Copy link
Contributor

for-loops really are pattern matches and do support destructuring. Our handling of tuple labels is just inconsistent enough that some of these cases work and some don't.

@palimondo
Copy link
Mannequin Author

palimondo mannequin commented May 10, 2017

@belkadan, wait, what?! Are you saying that the original example here is supposed to work?
Why does for-in loop get treated differently than closure arguments? That seems super inconsistent to me… What exactly is the difference between the variables you declare between for and in — that exist only inside the for-in block — and the closure arguments introduced before in keyword? As user I always thought they were the same!

@belkadan
Copy link
Contributor

One of these is assignment, like let, and one of them is defining parameters, like func. They're not actually related features at all, though I can see how a Haskell/ML person might want them to be.

To be fair, I'm not against adding destructuring-like capabilities to closures, but that would be a language change, and would have to go through the Swift Evolution Process.

@palimondo
Copy link
Mannequin Author

palimondo mannequin commented May 11, 2017

@belkadan, what would adding support for destructuring tuples in closure arguments entail in the compiler? Is that completely new feature, or it could reuse what's in for-each?

It looks like Reitzig (JIRA User) was suggesting the same thing in comments to SR-2008… maybe we should jointly draft an SE proposal?

@belkadan
Copy link
Contributor

It's 80% a new feature. The compiler would have to figure out what the proper type of the closure is anyway (the hard part) and then assign from that type into local variables for the destructured parameters (the easy part).

Please do take it to swift-evolution if you're interested!

@palimondo
Copy link
Mannequin Author

palimondo mannequin commented May 11, 2017

Any thoughts on requiring a let keyword to trigger the destructuting in order to remain source compatible as Reitzig (JIRA User) suggested in SR-2008? Wouldn't that make the implement significantly easier/able to reuse code from for-in? //cc CodaFi (JIRA User), @airspeedswift

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

3 participants