try? with a function that returns an optional


(Jonathan Bailey) #1

In the language guide on the apple website, https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html#//apple_ref/doc/uid/TP40014097-CH42-ID542

It says the following assignments to x and y are equivalent:
func someThrowingFunction() throws -> Int { ... }
let x = try? someThrowingFunction()
// x has type `Int?`

let y: Int?
do {
    y = try someThrowingFunction()
} catch {
    y = nil
}

However this isn’t the case if someThrowingFunction also returns an optional, say:

func someThrowingFunction() throws -> Int? { ... }

The type of x would be `Int??`, but the type of y is still `Int?`, is there some way to make the `try?` return an `Int?` instead of a double optional, which is not very helpful.

Thanks,
Jonathan


(Svein Halvor Halvorsen) #2

This is exactly according to the documentation.
In your first example `someThrowingFunction` returns an `Int`, so `y` is
defined as an `Int?`.
In the second example `someThrowingFunction` returns an `Int?`, so `y`
should be an `Int??`

However, since you didn't update the definition of `y` in your second
example, the if branch either assigns an `Int?` to an `Int?`, which is
legal, and may be nil, or it explicitly sets it to nil, which is also
legal. Thus, effectively unwrapping the nested optionals.

Yu could also apply a `flatMap` to the nested optional, like so:

let x = (try? someThrowingFunction())?.flatMap({$0})

I'm not sure if it's more readable, though.

···

2016-01-25 14:01 GMT+01:00 Jonathan Bailey via swift-users < swift-users@swift.org>:

In the language guide on the apple website,
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html#//apple_ref/doc/uid/TP40014097-CH42-ID542

It says the following assignments to x and y are equivalent:

   1. func someThrowingFunction() throws -> Int { ... }

   1. let x = try? someThrowingFunction()
   2. // x has type `Int?`
   3.
   4. let y: Int?
   5. do {
   6. y = try someThrowingFunction()
   7. } catch {
   8. y = nil
   9. }

However this isn’t the case if someThrowingFunction also returns an
optional, say:

   1. func someThrowingFunction() throws -> Int? { ... }

The type of x would be `Int??`, but the type of y is still `Int?`, is
there some way to make the `try?` return an `Int?` instead of a double
optional, which is not very helpful.

Thanks,
Jonathan

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


(Marco Masser) #3

If your function returns an Int? then there’s a reason for that and nil will mean something. And if your function can throw or return an Int? there will also be a very good reason for that and nil will also meaning something. If you then choose to use try? Swift has to return a double Optional because otherwise it would hide information from you. The outer Optional tells you whether there was an error and the inner Optional represents the return value of the function.

But to answer your question: If I’m not mistaken, there is no way to make try? unwrap the optional result of a function in case of success.

Is the function you’re calling one that you wrote? If so, I would try to find a way to make it return a non-optional Int. Maybe the case where it would return nil could be modeled as throwing an error?

Cheers,

Marco

···

On 2016-01-25, at 14:01, Jonathan Bailey via swift-users <swift-users@swift.org> wrote:

In the language guide on the apple website, https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html#//apple_ref/doc/uid/TP40014097-CH42-ID542

It says the following assignments to x and y are equivalent:
func someThrowingFunction() throws -> Int { ... }
let x = try? someThrowingFunction()
// x has type `Int?`

let y: Int?
do {
    y = try someThrowingFunction()
} catch {
    y = nil
}

However this isn’t the case if someThrowingFunction also returns an optional, say:

func someThrowingFunction() throws -> Int? { ... }

The type of x would be `Int??`, but the type of y is still `Int?`, is there some way to make the `try?` return an `Int?` instead of a double optional, which is not very helpful.

Thanks,
Jonathan

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


(Jonathan Bailey) #4

So it would be legal to change the type of y in the second example to `Int??`

Does that mean when assigning optionals, it will unwrap, check if it's nill and assign nil, else assign the original value? This seems kind of pointless to just assigning the complete optional

···

On 25 Jan 2016, at 15:49, Svein Halvor Halvorsen <svein.h@lvor.halvorsen.cc> wrote:

This is exactly according to the documentation.
In your first example `someThrowingFunction` returns an `Int`, so `y` is defined as an `Int?`.
In the second example `someThrowingFunction` returns an `Int?`, so `y` should be an `Int??`

However, since you didn't update the definition of `y` in your second example, the if branch either assigns an `Int?` to an `Int?`, which is legal, and may be nil, or it explicitly sets it to nil, which is also legal. Thus, effectively unwrapping the nested optionals.

Yu could also apply a `flatMap` to the nested optional, like so:

let x = (try? someThrowingFunction())?.flatMap({$0})

I'm not sure if it's more readable, though.

2016-01-25 14:01 GMT+01:00 Jonathan Bailey via swift-users <swift-users@swift.org>:

In the language guide on the apple website, https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html#//apple_ref/doc/uid/TP40014097-CH42-ID542

It says the following assignments to x and y are equivalent:
func someThrowingFunction() throws -> Int { ... }
let x = try? someThrowingFunction()
// x has type `Int?`

let y: Int?
do {
    y = try someThrowingFunction()
} catch {
    y = nil
}

However this isn’t the case if someThrowingFunction also returns an optional, say:

func someThrowingFunction() throws -> Int? { ... }

The type of x would be `Int??`, but the type of y is still `Int?`, is there some way to make the `try?` return an `Int?` instead of a double optional, which is not very helpful.

Thanks,
Jonathan

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


(Zhao Xin) #5

​I hope this will show something clearer to you. As you can see, y is
defined as OptionalInt?, which is Int??.

​typealias OptionInt = Int?

func someThrowingFunction() throws -> OptionInt {

    return OptionInt()

}

let y: OptionInt?
​​

do {

    y = try someThrowingFunction()

} catch {

    y = nil

}

z
​haoxin​

···

On Mon, Jan 25, 2016 at 11:54 PM, Jonathan Bailey via swift-users < swift-users@swift.org> wrote:

So it would be legal to change the type of y in the second example to
`Int??`

Does that mean when assigning optionals, it will unwrap, check if it's
nill and assign nil, else assign the original value? This seems kind of
pointless to just assigning the complete optional

On 25 Jan 2016, at 15:49, Svein Halvor Halvorsen < > svein.h@lvor.halvorsen.cc> wrote:

This is exactly according to the documentation.
In your first example `someThrowingFunction` returns an `Int`, so `y` is
defined as an `Int?`.
In the second example `someThrowingFunction` returns an `Int?`, so `y`
should be an `Int??`

However, since you didn't update the definition of `y` in your second
example, the if branch either assigns an `Int?` to an `Int?`, which is
legal, and may be nil, or it explicitly sets it to nil, which is also
legal. Thus, effectively unwrapping the nested optionals.

Yu could also apply a `flatMap` to the nested optional, like so:

let x = (try? someThrowingFunction())?.flatMap({$0})

I'm not sure if it's more readable, though.

2016-01-25 14:01 GMT+01:00 Jonathan Bailey via swift-users <
swift-users@swift.org>:

In the language guide on the apple website,
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html#//apple_ref/doc/uid/TP40014097-CH42-ID542

It says the following assignments to x and y are equivalent:

   1. func someThrowingFunction() throws -> Int { ... }

   1. let x = try? someThrowingFunction()
   2. // x has type `Int?`
   3.
   4. let y: Int?
   5. do {
   6. y = try someThrowingFunction()
   7. } catch {
   8. y = nil
   9. }

However this isn’t the case if someThrowingFunction also returns an
optional, say:

   1. func someThrowingFunction() throws -> Int? { ... }

The type of x would be `Int??`, but the type of y is still `Int?`, is
there some way to make the `try?` return an `Int?` instead of a double
optional, which is not very helpful.

Thanks,
Jonathan

_______________________________________________
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