[swift-evolution] try? shouldn't work on non-method-call

Sikhapol Saijit sikhapol at gmail.com
Thu Aug 18 03:23:38 CDT 2016


> On Aug 18, 2016, at 3:15 PM, Charles Srstka <cocoadev at charlessoft.com> wrote:
> 
> Sorry for the resend! Some of my previous e-mail was left out for some reason. Here it is again, as it should have been:
> 
>> On Aug 18, 2016, at 12:43 AM, Sikhapol Saijit via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> 1. Is it intentional that try? can be used with a "non-method-call" and return an optional of the type that follows?
> 
> a. I’m not sure what you mean by “non-method-call”, since the thing you called in your example *was* a function that was marked with “throws”. Using try? on a non-throwing function or method does indeed produce a warning.

In my sample code It did look like that try? was tied to the throwing function call but it actually operate on the result of the following as? operator.

So
if let a = try? couldFailButWillNot() as? Int { … }
was actually work like this:
if let a = try? (couldFailButWillNot() as? Int /* evaluated to Optional(42)) */) { … }

Try typing `print(try? 42)` in the playground and you will understand what I mean.

> 
> b. I’m not an Apple employee or a member of the development team, but I think it probably is intentional. There are two levels of optionality going on here; one, the possibility that the throwing method could have failed, and the other, that the optional result may or may not contain a value. Either of those two things being nil could mean quite different things, so the double-optional makes sense.
> 
>> 2. Should we design try? to have higher precedence than as? or any operators at all?
>> My intuition tells me that 
>> let a = try? couldFailButWillNot() as? Int
>> should be equivalent to
>> let a = (try? couldFailButWillNot()) as? Int 
> 
> This is more debatable whether it *should* be the case, but it’s worth pointing out that try/try?/try! work on the entire rest of the line, which means you can include more throwing calls and not have to put an ! each time:
> 
> func foo() throws -> Int { return 3 }
> 
> func bar() throws -> Int { return 5 }
> 
> if let i = try? foo() + bar() { // not try foo() + try bar()
>     print("i is \(i)")
> }
> 
> Or this:
> 
> func foo() throws -> Int { return 3 }
> 
> func bar(_ i: Int) throws -> Int { return i + 2 }
> 
> if let i = try? bar(foo()) { // not bar(try foo())
>     print("i is \(i)")
> }
> 
> So multiple throwing statements can be used on a single line without having to throw “try” all over the place. Now, whether that’s worth the admittedly confusing behavior you noted above is probably a decent topic for debate.
> 
> Charles

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160818/613b29da/attachment.html>


More information about the swift-evolution mailing list