> On Aug 18, 2016, at 8:46 AM, Xiaodi Wu <xiaodi...@gmail.com> wrote:
> The issue would be that, in the case of "try? foo()", nil and .some(nil) 
> might mean very different things.

This is true of a?.foo() as well.  But yes, I think it is more likely that 
someone would want to treat them differently for try?.

John.

> On Thu, Aug 18, 2016 at 10:40 John McCall <rjmcc...@apple.com 
> <mailto:rjmcc...@apple.com>> wrote:
>> On Aug 18, 2016, at 8:19 AM, Xiaodi Wu via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>> Lots of interesting points here. I do think there's an improvement possible 
>> here, but it's actually along the lines of Sam's original suggestion #3 (not 
>> vis-a-vis all of Swift, but specifically for how try? composes with as?):
>> 
>> A. I'm in favor of the current behavior where try prefixes an entire 
>> statement: it solves the precise issue of multiple nested optionals or 
>> multiple unwrapping of optionals in the situation where one statement has 
>> calls to many throwing functions. It says instead, I want nil if anything in 
>> this statement throws, otherwise, give me .some(value).
>> 
>> Sam--I think you may have misunderstood Charles's explanation. He's not 
>> saying "try?" attaches with lower or higher precedence as compared to "as?". 
>> Rather, I think the mental model is that "try?" prefixes the whole 
>> right-hand side (rhs), and if *any* call on the rhs throws, the whole rhs 
>> evaluates to nil, but if *any* call could potentially throw but doesn't, 
>> "try?" wraps the entire rhs and gives you .some(value). IMO, this is pretty 
>> sensible for the reason he gives.
>> 
>> B. I'm in favor of warning instead of error, for precisely the internal 
>> discussion rationale communicated by Slava. I'm willing to live with "try? 
>> 42" being only a warning if that means my code won't stop compiling when 
>> someone decides a library function doesn't need to throw.
>> 
>> Sam--here, changing warning to error would not solve your original problem, 
>> because in that example "try?" does prefix at least one throwing function, 
>> so you wouldn't get an error anyway.
>> 
>> C. However, given the thinking in (A), I do think how "try?" composes with 
>> "as?" is a little counterintuitive or at least overly ceremonious, though 
>> technically it is possible to reason through.
>> 
>> It's true that currently you can use the multiple nested optionals to figure 
>> out whether either a throwing function threw (but not which throwing 
>> function out of potentially more than one) or whether the cast did not 
>> succeed. But, since "try?" after all means "give me nil if anything throws," 
>> it kind of makes less sense that you get all this nesting and detailed 
>> information when it composes with "as?". If you really wanted that level of 
>> detail, you could always evaluate "try?" and "as?" in separate statements. 
>> What I'd propose instead is this:
>> 
>> If "try?" is composed with "as?", and "as?" yields "nil", then "try?" should 
>> not wrap that value in another optional.
> 
> We can't make the typing decision dependent on a dynamic property like 
> whether the cast fails.  And I don't like the idea of changing its typing 
> rule based on the form of the nested expression.  But we could make "try? 
> foo()" avoid adding an extra level of optionality, the same way that 
> "a?.foo()" does.
> 
> John.
> 
>> 
>> Does that sound sensible?
>> 
>> 
>> On Thu, Aug 18, 2016 at 3:54 AM, Sikhapol Saijit via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>>> On Aug 18, 2016, at 3:42 PM, Slava Pestov <spes...@apple.com 
>>> <mailto:spes...@apple.com>> wrote:
>>> 
>>>> 
>>>> On Aug 18, 2016, at 12:52 AM, David Hart via swift-evolution 
>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>>> 
>>>> Opinions inline:
>>>> 
>>>>> On 18 Aug 2016, at 07:43, Sikhapol Saijit via swift-evolution 
>>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>>>> 
>>>>> Hi all,
>>>>> 
>>>>> 
>>>>> Yesterday I tried this code:
>>>>> 
>>>>> func couldFailButWillNot() throws -> Any {
>>>>>     return 42
>>>>> }
>>>>> 
>>>>> if let a = try? couldFailButWillNot() as? Int {
>>>>>     print(a)
>>>>> }
>>>>> 
>>>>> And was surprised that the output was Optional(42) on both Swift 2 and 
>>>>> Swift 3.
>>>>> I always have the impression that when a variable is resolved with if let 
>>>>> it will never be optional.
>>>>> 
>>>>> So, with a little investigation, I found out that it happens because as? 
>>>>> has higher precedence than try? and is evaluated first.
>>>>> And the whole expression `try? couldFailButWillNot() as? Int` evaluated 
>>>>> as Optional(Optional(42)).
>>>>> 
>>>>> Also, I’m surprised that try? can be used with non-method-call.
>>>>> This code: `print(try? 42)` will print Optional(42).
>>>>> 
>>>>> So, the questions are:
>>>>> 
>>>>> 1. Is it intentional that try? can be used with a "non-method-call" and 
>>>>> return an optional of the type that follows?
>>>> 
>>>> I think this is the real solution. try and try? should not be allowed on 
>>>> non-throwing functions or expressions.
>>> 
>>> This is a warning right now — do you think it should be an error?
>>> 
>>> Slavas-MacBook-Pro:~ slava$ cat ttt.swift 
>>> func f() {}
>>> 
>>> func g() {
>>>   try f()
>>>   try? f()
>>> }
>>> 
>>> Slavas-MacBook-Pro:~ slava$ swiftc ttt.swift 
>>> ttt.swift:4:3: warning: no calls to throwing functions occur within 'try' 
>>> expression
>>>   try f()
>>>   ^
>>> ttt.swift:5:8: warning: no calls to throwing functions occur within 'try' 
>>> expression
>>>   try? f()
>>>        ^
>> 
>> Thank you Slava,
>> 
>> While I think using try/try? on anything but a throwing function call should 
>> be an error, right now it even works with anything. `try? 42` will just wrap 
>> 42 in an optional and give some warning now.
>> 
>>> 
>>>> 
>>>>> 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 
>>>> 
>>>> That’s worth considering. try feels like it should tie very strongly with 
>>>> the throwing expression.
>>>> 
>>>>> 3. Do you think that doubly-nested optional (or multi-level-nested 
>>>>> optional) is confusing and should be removed from Swift? (Yes, I’ve seen 
>>>>> this blog post Optionals Case Study: valuesForKeys 
>>>>> <https://developer.apple.com/swift/blog/?id=12>).
>>>>> For me Optional(nil) (aka Optional.Some(Optional.None))) doesn’t make 
>>>>> much sense. 
>>>>> Maybe, one of the solution is to always have optional of optional merged 
>>>>> into a single level optional? Like Optional(Optional(Optional(42))) 
>>>>> should be the merged to and evaluated as Optional(42).
>>>> 
>>>> I don’t think this is the solution. Even if it was, how would you expect 
>>>> to “remove” them from Swift? Optionals are simply an enum with an 
>>>> associated value. We’d have to introduce a language feature to restrict 
>>>> values that can be stored in enum cases? It sounds awfully complicated.
>>>> 
>>>>> BTW, the code above is merely for a demonstration. The actual code was 
>>>>> more of something like this:
>>>>> 
>>>>> func parse(JSON: Data) throws -> Any {
>>>>>     // …
>>>>> }
>>>>> 
>>>>> if let dict = try? parse(JSON: json) as? [String: Any] {
>>>>>     // assume dict is a valid [String: Any] dictionary
>>>>>     // …
>>>>> }
>>>>> 
>>>>> I’m new to this mailing list so I’m not sure if this belongs here. I’m 
>>>>> sorry in advance if it doesn’t.
>>>>> 
>>>>> 
>>>>> Thank you,
>>>>> Sam
>>>>> _______________________________________________
>>>>> swift-evolution mailing list
>>>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>> 
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to