> 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