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

2016-08-18 Thread Braeden Profile via swift-evolution
I do think that the status quo is good for try? precedence and such, but how 
about the original problem? The code was hard to work with because it used a 
double nested Optional.  If you really don’t care about the reason that code 
failed, then a single optional should be returned.  There’s this:

if let rawA = try? couldFailButWillNot(),
   let a = rawA as? Int
{
print(a)
}

…but it seems overly verbose.  I think it would be easier if the standard 
library included flatMap()’s companion, flattened() Optional>, much 
like the existing flatMap() and flatten() of Array>.  Unfortunately, 
this isn’t really possible:

extension Optional where Wrapped == Optional
{
func flattened() -> Wrapped
{
if let wrapped = self
{ return wrapped }
else
{ return nil }
}
}

if let a = (try? couldFailButWillNot() as? Int).flattened() {
print(a)
}

…as the compiler complains that “T” is unresolved and that you can’t constrain 
an extension with a generic type—or any non-protocol type, for that matter.  A 
free flattened() function would work, but wouldn’t be very clean or intuitive.  
flatMap works for now, but isn’t great:

if let a = (try? couldFailButWillNot() as? Int)?.flatMap({$0}) {
print(a)
}

I guess that feature will have to wait until Swift 4.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2016-08-18 Thread Xiaodi Wu via swift-evolution
On Thu, Aug 18, 2016 at 1:20 PM, John McCall  wrote:

> On Aug 18, 2016, at 10:11 AM, Xiaodi Wu  wrote:
> On Thu, Aug 18, 2016 at 11:30 AM, John McCall  wrote:
>
>> On Aug 18, 2016, at 8:46 AM, Xiaodi Wu  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?.
>>
>
> Agreed.
>
> My proposed solution was half-baked, but it may be workable--I'm not
> suggesting typing decisions based on a dynamic property, of course. It'd be
> something like this:
>
> `as?` would produce a result of a type named something like
> CastingOptional, which on assignment or essentially any other operation
> is promoted/bridged/[insert much more correct term here] to an Optional
> like how T is automatically promoted to Optional. However, `try?` will
> not wrap a CastingOptional into an Optional>.
>
>
> The way this is done for ?-chaining is that the result of the chain is
> coerced to T?, for a fresh unbound type T.  If the result is already of
> type U?, T will be bound to U and there's no "stacking" of optionals; if
> the result is a non-optional type V, T will be bound to V and therefore the
> chain gains a level of optionality.  I think that is simpler and more
> consistent than inventing a new flavor of Optional with complex conversion
> and defaulting rules.
>

Yeah, that's definitely much simpler.

I'm just not sure I'd be comfortable with `try?` refusing to stack
optionals for all arbitrary functions `(...) -> Optional` just like it
works for ?-chaining, for the reasons we just discussed. So, if we're to
stick to consistent rules, I'd rather that `try?` continue to stack
optionals all the time.

The status quo isn't unteachable: if you have try? and as?, that's two
question marks, so you get back two stacked optionals. That's livable.


> John.
>
>
>
>> John.
>>
>> On Thu, Aug 18, 2016 at 10:40 John McCall  wrote:
>>
>>> On Aug 18, 2016, at 8:19 AM, Xiaodi Wu via swift-evolution <
>>> 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

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

2016-08-18 Thread John McCall via swift-evolution
> On Aug 18, 2016, at 10:11 AM, Xiaodi Wu  wrote:
> On Thu, Aug 18, 2016 at 11:30 AM, John McCall  > wrote:
>> On Aug 18, 2016, at 8:46 AM, Xiaodi Wu > > 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?.
> 
> Agreed.
> 
> My proposed solution was half-baked, but it may be workable--I'm not 
> suggesting typing decisions based on a dynamic property, of course. It'd be 
> something like this:
> 
> `as?` would produce a result of a type named something like 
> CastingOptional, which on assignment or essentially any other operation is 
> promoted/bridged/[insert much more correct term here] to an Optional like 
> how T is automatically promoted to Optional. However, `try?` will not wrap 
> a CastingOptional into an Optional>.

The way this is done for ?-chaining is that the result of the chain is coerced 
to T?, for a fresh unbound type T.  If the result is already of type U?, T will 
be bound to U and there's no "stacking" of optionals; if the result is a 
non-optional type V, T will be bound to V and therefore the chain gains a level 
of optionality.  I think that is simpler and more consistent than inventing a 
new flavor of Optional with complex conversion and defaulting rules.

John.

>  
> John.
> 
>> On Thu, Aug 18, 2016 at 10:40 John McCall > > wrote:
>>> On Aug 18, 2016, at 8:19 AM, Xiaodi Wu via swift-evolution 
>>> 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 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
 On Aug 18, 2016, at 3:42 PM, Slava Pestov >>> > wrote:
 
> 
> On Aug 18, 2016, at 12:52 AM, David Hart via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:

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

2016-08-18 Thread John McCall via swift-evolution
> On Aug 18, 2016, at 10:56 AM, Davor Jankolija  wrote:
>> On 18 Aug 2016, at 19:46, John McCall > > wrote:
>> 
>>> On Aug 18, 2016, at 10:15 AM, Davor Jankolija via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
 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()
 ^
>>> 
>>> IMHO at least, this should be an error. As a side note I do think that try 
>>> should have greater precedence than as, even though this does potentially 
>>> limit calls that would use only one try on a series of throwing statement 
>>> that can be handled using parentheses. The benefit is that try is probably 
>>> called in the vast majority of situations (that’s my experience at least) 
>>> on a single throw statement and having it have higher precedance would 
>>> avoid some surprises as most developers probably already assume that try 
>>> wil be executed before as.
>> 
>> The design of ordinary 'try' and 'try!' are that they includes the entire 
>> expression to the right, spanning casts and other binary operators, and I 
>> think that's clearly the right rule for them.  It's not as clearly right for 
>> 'try?', but making 'try' and 'try?' be parsed differently would be horribly 
>> confusing.
>> 
>> John.
> 
> I see what you’re saying and I have to agree for the most part, it’s just 
> that now you basically get a ‘try’ executed on the result of the ‘as?’ 
> expression, which although is correct now that I look at your explanation is 
> somewhat unintuitive, again this is just my opinion.
> 
> P.S.
> It would seem then, that the best way and probably simplest is to remember 
> and place parentheses around the ‘try call()’ and then attempt a cast?

In your case, yes, I think the right solution is probably to parenthesize the 
try?.

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


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

2016-08-18 Thread Davor Jankolija via swift-evolution

> On 18 Aug 2016, at 19:46, John McCall  wrote:
> 
>> On Aug 18, 2016, at 10:15 AM, Davor Jankolija via swift-evolution 
>>  wrote:
>> 
>>> 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()
>>> ^
>> 
>> IMHO at least, this should be an error. As a side note I do think that try 
>> should have greater precedence than as, even though this does potentially 
>> limit calls that would use only one try on a series of throwing statement 
>> that can be handled using parentheses. The benefit is that try is probably 
>> called in the vast majority of situations (that’s my experience at least) on 
>> a single throw statement and having it have higher precedance would avoid 
>> some surprises as most developers probably already assume that try wil be 
>> executed before as.
> 
> The design of ordinary 'try' and 'try!' are that they includes the entire 
> expression to the right, spanning casts and other binary operators, and I 
> think that's clearly the right rule for them.  It's not as clearly right for 
> 'try?', but making 'try' and 'try?' be parsed differently would be horribly 
> confusing.
> 
> John.

I see what you’re saying and I have to agree for the most part, it’s just that 
now you basically get a ‘try’ executed on the result of the ‘as?’ expression, 
which although is correct now that I look at your explanation is somewhat 
unintuitive, again this is just my opinion.

P.S.
It would seem then, that the best way and probably simplest is to remember and 
place parentheses around the ‘try call()’ and then attempt a cast?

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


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

2016-08-18 Thread John McCall via swift-evolution
> On Aug 18, 2016, at 10:15 AM, Davor Jankolija via swift-evolution 
>  wrote:
> 
>> 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()
>>  ^
> 
> IMHO at least, this should be an error. As a side note I do think that try 
> should have greater precedence than as, even though this does potentially 
> limit calls that would use only one try on a series of throwing statement 
> that can be handled using parentheses. The benefit is that try is probably 
> called in the vast majority of situations (that’s my experience at least) on 
> a single throw statement and having it have higher precedance would avoid 
> some surprises as most developers probably already assume that try wil be 
> executed before as.

The design of ordinary 'try' and 'try!' are that they includes the entire 
expression to the right, spanning casts and other binary operators, and I think 
that's clearly the right rule for them.  It's not as clearly right for 'try?', 
but making 'try' and 'try?' be parsed differently would be horribly confusing.

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


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

2016-08-18 Thread Davor Jankolija via swift-evolution

> 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()
>   ^

IMHO at least, this should be an error. As a side note I do think that try 
should have greater precedence than as, even though this does potentially limit 
calls that would use only one try on a series of throwing statement that can be 
handled using parentheses. The benefit is that try is probably called in the 
vast majority of situations (that’s my experience at least) on a single throw 
statement and having it have higher precedance would avoid some surprises as 
most developers probably already assume that try wil be executed before as.

— Davor
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2016-08-18 Thread Xiaodi Wu via swift-evolution
On Thu, Aug 18, 2016 at 11:30 AM, John McCall  wrote:

> On Aug 18, 2016, at 8:46 AM, Xiaodi Wu  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?.
>

Agreed.

My proposed solution was half-baked, but it may be workable--I'm not
suggesting typing decisions based on a dynamic property, of course. It'd be
something like this:

`as?` would produce a result of a type named something like
CastingOptional, which on assignment or essentially any other operation
is promoted/bridged/[insert much more correct term here] to an Optional
like how T is automatically promoted to Optional. However, `try?` will
not wrap a CastingOptional into an Optional>.


> John.
>
> On Thu, Aug 18, 2016 at 10:40 John McCall  wrote:
>
>> On Aug 18, 2016, at 8:19 AM, Xiaodi Wu via swift-evolution <
>> 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> wrote:
>>
>>>
>>> On Aug 18, 2016, at 3:42 PM, Slava Pestov  wrote:
>>>
>>>
>>> On Aug 18, 2016, at 12:52 AM, David Hart via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>> Opinions inline:
>>>
>>> On 18 Aug 2016, at 07:43, Sikhapol Saijit via swift-evolution <
>>> 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))*.
>>>
>>> 

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

2016-08-18 Thread John McCall via swift-evolution
> On Aug 18, 2016, at 8:46 AM, Xiaodi Wu  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  > wrote:
>> On Aug 18, 2016, at 8:19 AM, Xiaodi Wu via swift-evolution 
>> 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 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>>> On Aug 18, 2016, at 3:42 PM, Slava Pestov >> > wrote:
>>> 
 
 On Aug 18, 2016, at 12:52 AM, David Hart via swift-evolution 
 mailto:swift-evolution@swift.org>> wrote:
 
 Opinions inline:
 
> On 18 Aug 2016, at 07:43, Sikhapol Saijit via swift-evolution 
> 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 

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

2016-08-18 Thread Xiaodi Wu via swift-evolution
The issue would be that, in the case of "try? foo()", nil and .some(nil)
might mean very different things.
On Thu, Aug 18, 2016 at 10:40 John McCall  wrote:

> On Aug 18, 2016, at 8:19 AM, Xiaodi Wu via swift-evolution <
> 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> wrote:
>
>>
>> On Aug 18, 2016, at 3:42 PM, Slava Pestov  wrote:
>>
>>
>> On Aug 18, 2016, at 12:52 AM, David Hart via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> Opinions inline:
>>
>> On 18 Aug 2016, at 07:43, Sikhapol Saijit via swift-evolution <
>> 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*
>>  

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

2016-08-18 Thread John McCall via swift-evolution
> On Aug 18, 2016, at 8:19 AM, Xiaodi Wu via swift-evolution 
>  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 
> mailto:swift-evolution@swift.org>> wrote:
> 
>> On Aug 18, 2016, at 3:42 PM, Slava Pestov > > wrote:
>> 
>>> 
>>> On Aug 18, 2016, at 12:52 AM, David Hart via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> Opinions inline:
>>> 
 On 18 Aug 2016, at 07:43, Sikhapol Saijit via swift-evolution 
 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 S

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

2016-08-18 Thread Xiaodi Wu via swift-evolution
On Thu, Aug 18, 2016 at 10:19 AM, Xiaodi Wu  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
>

(Here, I meant to say, if *all* calls that could potentially throw don't
throw...)


> 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.
>
> Does that sound sensible?
>
>
> On Thu, Aug 18, 2016 at 3:54 AM, Sikhapol Saijit via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>>
>> On Aug 18, 2016, at 3:42 PM, Slava Pestov  wrote:
>>
>>
>> On Aug 18, 2016, at 12:52 AM, David Hart via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> Opinions inline:
>>
>> On 18 Aug 2016, at 07:43, Sikhapol Saijit via swift-evolution <
>> 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

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

2016-08-18 Thread Xiaodi Wu via swift-evolution
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.

Does that sound sensible?


On Thu, Aug 18, 2016 at 3:54 AM, Sikhapol Saijit via swift-evolution <
swift-evolution@swift.org> wrote:

>
> On Aug 18, 2016, at 3:42 PM, Slava Pestov  wrote:
>
>
> On Aug 18, 2016, at 12:52 AM, David Hart via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Opinions inline:
>
> On 18 Aug 2016, at 07:43, Sikhapol Saijit via swift-evolution <
> 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 see

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

2016-08-18 Thread Sikhapol Saijit via swift-evolution

> On Aug 18, 2016, at 3:42 PM, Slava Pestov  wrote:
> 
>> 
>> On Aug 18, 2016, at 12:52 AM, David Hart via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> Opinions inline:
>> 
>>> On 18 Aug 2016, at 07:43, Sikhapol Saijit via swift-evolution 
>>> 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 
>>> ).
>>> 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 
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> 
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2016-08-18 Thread Slava Pestov via swift-evolution

> On Aug 18, 2016, at 1:42 AM, Slava Pestov via swift-evolution 
>  wrote:
> 
>> 
>> On Aug 18, 2016, at 12:52 AM, David Hart via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> Opinions inline:
>> 
>>> On 18 Aug 2016, at 07:43, Sikhapol Saijit via swift-evolution 
>>> 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()
>^

… Replying to myself: I also think it would be more logical for this to be an 
error, but I vaguely recall some internal discussion where we agreed that 
removing ‘throws’ from a function should not break source or binary 
compatibility (I don’t know if the current implementation makes good on the 
latter).

Jordan, do you remember the reasoning for this being a warning and not an error?

> 
>> 
>>> 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 
>>> ).
>>> 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 
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> 
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2016-08-18 Thread Slava Pestov via swift-evolution

> On Aug 18, 2016, at 12:52 AM, David Hart via swift-evolution 
>  wrote:
> 
> Opinions inline:
> 
>> On 18 Aug 2016, at 07:43, Sikhapol Saijit via swift-evolution 
>> 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()
   ^

> 
>> 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 
>> ).
>> 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 
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2016-08-18 Thread Sikhapol Saijit via swift-evolution

> On Aug 18, 2016, at 3:15 PM, Charles Srstka  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 
>> mailto:swift-evolution@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

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


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

2016-08-18 Thread Charles Srstka via swift-evolution
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 
> mailto:swift-evolution@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.

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___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2016-08-18 Thread Charles Srstka via swift-evolution
> On Aug 18, 2016, at 12:43 AM, Sikhapol Saijit via swift-evolution 
>  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.

b. I’m not a member of the development team, but I think it probably is 
intentional. There are two levels of optionality going on here; 

> 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

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


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

2016-08-18 Thread David Hart via swift-evolution
Opinions inline:

> On 18 Aug 2016, at 07:43, Sikhapol Saijit via swift-evolution 
>  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.

> 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 
> ).
> 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
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


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

2016-08-17 Thread Sikhapol Saijit via swift-evolution
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?

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 

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 
).
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).

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
https://lists.swift.org/mailman/listinfo/swift-evolution