try? works on non-method-call?


(Sikhapol Saijit) #1

Hi Swift Community,

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.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 non-method-call and return an optional of the type that follows?

2. Should we design `try?` to have higher precedence than `as?`.
My intuition tells me that
`let a = try? couldFailButWillNot() as? Int`
and
`let a = (try? couldFailButWillNot()) as? Int`
should be equivalent.

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 <https://developer.apple.com/swift/blog/?id=12>))
For me “Optional(nil)” (aka “Optional.Some(Optional.None))”) doesn’t make any sense at all.
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 Optional(42).

Thank you
Sikhapol Saijit (Sam)
iOS Developer, Taskworld, Bangkok


(David Hart) #2

I think that on error or warning like this is the right solution.

···

On 21 Jul 2016, at 08:13, Sikhapol Saijit via swift-users <swift-users@swift.org> wrote:

1. Is it intentional that `try?` can be used with non-method-call and return an optional of the type that follows?


(Nicholas Outram) #3

The issue is related to the as?

Try this:

if let a = try? couldFailButWillNot() {
   print(a)
}

Nick

···

On 21 Jul 2016, at 07:13, Sikhapol Saijit via swift-users <swift-users@swift.org> wrote:

Hi Swift Community,

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.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 non-method-call and return an optional of the type that follows?

2. Should we design `try?` to have higher precedence than `as?`.
My intuition tells me that
`let a = try? couldFailButWillNot() as? Int`
and
`let a = (try? couldFailButWillNot()) as? Int`
should be equivalent.

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 <https://developer.apple.com/swift/blog/?id=12>))
For me “Optional(nil)” (aka “Optional.Some(Optional.None))”) doesn’t make any sense at all.
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 Optional(42).

Thank you
Sikhapol Saijit (Sam)
iOS Developer, Taskworld, Bangkok
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Nicholas Outram) #4

Are we saying this function

func couldFailButWillNot() throws -> Any {
  return 42
}

has an implicit Int return type?

If so, there is actually no need for as? (which will result in an Optional - which I thought that was the behaviour in Swift 2 as well?)

···

On 21 Jul 2016, at 08:59, Nicholas Outram via swift-users <swift-users@swift.org> wrote:

The issue is related to the as?

Try this:

if let a = try? couldFailButWillNot() {
   print(a)
}

Nick

On 21 Jul 2016, at 07:13, Sikhapol Saijit via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

Hi Swift Community,

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.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 non-method-call and return an optional of the type that follows?

2. Should we design `try?` to have higher precedence than `as?`.
My intuition tells me that
`let a = try? couldFailButWillNot() as? Int`
and
`let a = (try? couldFailButWillNot()) as? Int`
should be equivalent.

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 <https://developer.apple.com/swift/blog/?id=12>))
For me “Optional(nil)” (aka “Optional.Some(Optional.None))”) doesn’t make any sense at all.
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 Optional(42).

Thank you
Sikhapol Saijit (Sam)
iOS Developer, Taskworld, Bangkok
_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users

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


(Sikhapol Saijit) #5

Hi Nick,

The code was simplified for demonstration.
You’re right that in a simple case like that I wouldn’t need to use `as?`.

In my actual case it was 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
    // …
}

Sure, this could be written as:

if let jsonObject = try? parse(JSON: json),
let dict = jsonObject as? [String: Any] {
    // …
}

But I just wonder why the first case behave as it does and whether it should.

Sam

···

On Jul 21, 2016, at 3:03 PM, Nicholas Outram <nicholas.outram@icloud.com> wrote:

Are we saying this function

func couldFailButWillNot() throws -> Any {
  return 42
}

has an implicit Int return type?

If so, there is actually no need for as? (which will result in an Optional - which I thought that was the behaviour in Swift 2 as well?)

On 21 Jul 2016, at 08:59, Nicholas Outram via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

The issue is related to the as?

Try this:

if let a = try? couldFailButWillNot() {
   print(a)
}

Nick

On 21 Jul 2016, at 07:13, Sikhapol Saijit via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

Hi Swift Community,

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.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 non-method-call and return an optional of the type that follows?

2. Should we design `try?` to have higher precedence than `as?`.
My intuition tells me that
`let a = try? couldFailButWillNot() as? Int`
and
`let a = (try? couldFailButWillNot()) as? Int`
should be equivalent.

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 <https://developer.apple.com/swift/blog/?id=12>))
For me “Optional(nil)” (aka “Optional.Some(Optional.None))”) doesn’t make any sense at all.
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 Optional(42).

Thank you
Sikhapol Saijit (Sam)
iOS Developer, Taskworld, Bangkok
_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users


(Zhao Xin) #6

I think the best way is

do {

    let a = try couldFailButWillNot()

    if let b = a as? Int {

        print(b)

    }

} catch let error {

    print(error)

}

It is longer, but much clearer.

Below code will work, but not as clear. You don't know whether it is a or b
causes the failure. It is not a good practice to use try? if that is not on
purpose.

if let a = try? couldFailButWillNot(), let b = a as? Int {

    print(b)

}
or

if let a = (try? couldFailButWillNot()) as? Int {

    print(a)

}

Zhaoxin

···

On Thu, Jul 21, 2016 at 4:25 PM, Sikhapol Saijit via swift-users < swift-users@swift.org> wrote:

Hi Nick,

The code was simplified for demonstration.
You’re right that in a simple case like that I wouldn’t need to use `as?`.

In my actual case it was 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
    // …
}

Sure, this could be written as:

if let jsonObject = try? parse(JSON: json),
let dict = jsonObject as? [String: Any] {
    // …
}

But I just wonder why the first case behave as it does and whether it
should.

Sam

On Jul 21, 2016, at 3:03 PM, Nicholas Outram <nicholas.outram@icloud.com> > wrote:

Are we saying this function

func couldFailButWillNot() throws -> Any {
  return 42
}

has an implicit Int return type?

If so, there is actually no need for as? (which will result in an Optional
- which I thought that was the behaviour in Swift 2 as well?)

On 21 Jul 2016, at 08:59, Nicholas Outram via swift-users < > swift-users@swift.org> wrote:

The issue is related to the as?

Try this:

if let a = try? couldFailButWillNot() {
   print(a)
}

Nick

On 21 Jul 2016, at 07:13, Sikhapol Saijit via swift-users < > swift-users@swift.org> wrote:

Hi Swift Community,

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.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 non-method-call and
return an optional of the type that follows?

2. Should we design `try?` to have higher precedence than `as?`.
My intuition tells me that
`let a = try? couldFailButWillNot() as? Int`
and
`let a = (try? couldFailButWillNot()) as? Int`
should be equivalent.

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
any sense at all.
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 Optional(42).

Thank you
Sikhapol Saijit (Sam)
iOS Developer, Taskworld, Bangkok
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

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

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