4

Swift 2.0 added do {} catch {} which can be used like so:

do {
    let jsonData = try NSJSONSerialization.dataWithJSONObject(params, options: []);
} catch let jsonError as NSError {
    print(jsonError);
}

but I've also seen in in my 2.0 converted classes the catch implemented with an underscore:

do {
    let jsonData = try NSJSONSerialization.dataWithJSONObject(params, options: []);
} catch _ {

}

what makes it especially confusing is why not just provide nothing after catch which is perfectly valid code:

do {
    let jsonData = try NSJSONSerialization.dataWithJSONObject(params, options: []);
} catch {

}

What is that underscore _, what can I do with it, how would I implement that in my own function signatures? In the previous Swift 1.2 declaration I didn't use the NSError so it makes sense that the conversion is throwing the error away but why use _?

Shizam
  • 9,627
  • 8
  • 51
  • 82
  • 1
    @Aaron Brager if you read both questions carefully you'll see that they are not actually related, my question isn't about method signatures. – Shizam Jul 10 '15 at 00:05
  • Presumably it just means that you are not assigning any name to an error you catch and hence not declaring it. Maybe this is preferable if you don't actually want to do anything with the error in the catch block. – myles Jul 10 '15 at 00:07
  • @myles thats what I thought as well but if that were the case you can just not provide anything after the catch statement, ie it just says `catch {` so why would it convert to having a `_`? – Shizam Jul 10 '15 at 00:08
  • Did Xcode automatically convert it from a declaration to an underscore or was it explicitly written this way? If automatically converted I've read that it can do this if the previously declared variable wasn't actually used in the following block. So in your example above, if `jsonError` wasn't actually used in the catch block Xcode may automatically conver this to `_`. If it's because of this maybe they just didn't implement the process cleverly enough to do it without an `_` if one isn't required. – myles Jul 10 '15 at 00:14
  • @myles Yes, xcode automatically converted it and as you mention, the previously declared variable wasn't used so it makes sense that it would convert it to something that "throws away" the `error` but why throw it away with this mystery `_`? – Shizam Jul 10 '15 at 00:19
  • The `_` isn't really that mysterious. It's used all over the place. You can "throw away" other things too. `if let _ = foo as? String {`... – nhgrif Jul 10 '15 at 00:19
  • 1
    I think because it does this convert with other things too, like with `if let ...` if the variable name was not actually used in the following block. If they were to not put the `_` in these places the code wouldn't actually work. Hence it does `_` everywhere to be safe, even though in some places you may not actually need it. – myles Jul 10 '15 at 00:21
  • I'm voting to close this question as off-topic because it's primarily opinion based (short of someone who worked on the tool that converts from Swift 1.2 to Swift 2, all anyone can do is speculate), and in the end, the answer doesn't really actually even matter... – nhgrif Jul 10 '15 at 00:22
  • @myles I think you're right, in this case `(nothing)` and `_` are exactly the same, if you answer that I'll mark it as the correct one. – Shizam Jul 10 '15 at 00:24

2 Answers2

3

You're asking a question about an automatic conversion. It's just a starting place! Apple doesn't know what you want to do, so they provide a completely minimal neutral catch-all catch block — it does nothing at all, but we compile because there's a catch-all. Obviously if you want to capture the error variable, you will delete the _ and capture the error variable. You might want to do much more, e.g. write a more focused catch block. It's up to you to build on the foundation you've been given.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • That makes sense @matt, part of the problem was "why not just provide nothing instead of _?" which made it seem like there was some special distinction when really it seems like `_` and `(nothing)` are the same. Which still makes me wonder how/why Apple lets you accomplish the same thing two different ways... – Shizam Jul 10 '15 at 00:25
  • 2
    @Shizam Because of other places where the `_` is actually useful. You can use `_` *anywhere* you can declare a variable. Why should `catch` blocks be the exception to the rule? – nhgrif Jul 10 '15 at 00:27
  • 1
    @Shizam But you already gave the answer. There _is_ a distinction: "nothing" lets the `error` variable arrive into the catch block. The `_`, exactly as in a switch case, mops up the error _and prevents it from entering the catch block_. This is a catch block so minimal that it does absolutely nothing. That's what I said in my answer, I believe. – matt Jul 10 '15 at 00:35
  • Woah ho ho, @matt is right, `nothing` lets the error through! Well, that was unexpected. – Shizam Jul 10 '15 at 00:42
  • 1
    @Shizam It's not actually unexpected. It's very well documented! :) The `error` variable exists inside a catch block _only_ if that catch block's pattern is completely empty. – matt Jul 10 '15 at 00:55
  • 2
    @Shizam One more little thing; I've never used the automatic Swift 2.0 updater. I like to decline the automatic update, try to compile, fail, and fix all the problems myself. I've learned much more about Swift 2.0 by doing that! – matt Jul 10 '15 at 00:56
  • @matt Agreed on not trusting the auto-updater, I just took the opposite approach which was let it do its thing and then go through change-by-change and see what it suggested and then over-analyze _why it picked that way_ :) – Shizam Jul 10 '15 at 04:11
2

If the variable declared before the catch block isn't actually used in the following block then Xcode will automatically convert this to an _ since it is not used. So in your example above, if jsonError wasn't actually used in the catch block, Xcode may automatically convert this to _. This isn't just for do {} catch {} but also things such as if let ... { }.

I think because it does this convert with other things too, like the if let ... {}, if they were to not put the _ in these places the code wouldn't actually work. Hence it does _ everywhere to be safe, even though in some places you may not actually need it.

myles
  • 1,681
  • 1
  • 15
  • 27
  • This is the problem with opinion-based questions. They can only illicit opinion-based answers. This answer is marked as accepted based on comments following "I think..."... – nhgrif Jul 10 '15 at 00:32
  • @nhgrif There are two aspects to the question here "Why did it convert it this way?" and "What is the difference btw _ and (nothing)". While the former may lend itself to (some) speculation the latter doesn't and this clarifies that bit. – Shizam Jul 10 '15 at 00:41