nested optionals

35 views
Skip to first unread message

Alex Hall

unread,
Sep 15, 2015, 9:19:16 AM9/15/15
to swift-l...@googlegroups.com
Hey all,
I was running into a weird problem in an app, where I unwrapped an optional but was still getting an optional. I made a Playground to test it out, and discovered that Swift can nest optionals within optionals. Is this intended behavior?

let dict:[String:String?] = ["id":"5"]
let myInt:Int? = Int(dict["id"]!!) //note the two exclamation marks

print("myInt is \(myInt!)")

If you remove one of the two exclamation marks from the myInt line, you get an error that the optional was not unwrapped. Looks like Swift can have an optional as the non-nil value of an optional, and a single unwrap isn't enough to collapse all the optionals stored inside and give you the non-nil value at the end. I'm guessing this is how it's supposed to work, but it threw me off at first; I expected to unwrap an optional and get a non-optional value, not another optional. I can see the logic behind this way of doing things, I just never knew it existed and wanted to check that this is, in fact, how it's supposed to work.

--
Have a great day,
Alex Hall
meh...@icloud.com

Daniel Tartaglia

unread,
Sep 15, 2015, 9:26:33 AM9/15/15
to Alex Hall, swift-l...@googlegroups.com
Yes this is expected behavior. You got a monad in your monad! :-) 

You have this: 

let dict: Dictionary<String, Optional<String>> = ["id": "5"]
let item: Optional<Optional<String>> = dict["id"]


--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swift-languag...@googlegroups.com.
To post to this group, send email to swift-l...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/329819FD-5168-44DF-A637-3C6F6A4BA073%40icloud.com.
For more options, visit https://groups.google.com/d/optout.

Daniel Tartaglia

unread,
Sep 15, 2015, 9:37:08 AM9/15/15
to Alex Hall, swift-l...@googlegroups.com
Fun with flatMap!

let dict:[String: String?] = ["id": "5"]
let myInt = dict["id"].flatMap { $0.flatMap { Int($0) } }
print("myInt is \(myInt!)")

On Sep 15, 2015, at 9:19 AM, Alex Hall <meh...@icloud.com> wrote:

Jeremy Pereira

unread,
Sep 16, 2015, 12:39:13 PM9/16/15
to Alex Hall, swift-l...@googlegroups.com
To me it looks like it is as expected. The value type in the dictionary is Optional<String> The subscript return value is the value type of the dictionary wrapped in an Optional i.e. Optional<Optional<String>>

Why would you expect anything else?

Alex Hall

unread,
Sep 16, 2015, 1:00:05 PM9/16/15
to Jeremy Pereira, swift-l...@googlegroups.com

> On Sep 16, 2015, at 12:39, Jeremy Pereira <jeremy.j...@googlemail.com> wrote:
>
> To me it looks like it is as expected. The value type in the dictionary is Optional<String> The subscript return value is the value type of the dictionary wrapped in an Optional i.e. Optional<Optional<String>>
>
> Why would you expect anything else?

As I said, I get the logic, I just thought I'd check. The way I learned it, an optional can have either a value or nil, which is the whole point of optionals. No one ever told me that the non-nil value in an optional can be another optional, so I figured it could be relied on to always be a non-optional. I'd never seen it before, and had never run across it in reading anything or talking to others about Swift, so I never expected it to work that way. Basically, I just didn't realize that Swift supports letting an optional be the non-nil value of an optional. I wanted to check to be sure it wasn't something odd, or that I wasn't doing something wrong.

Jeremy Pereira

unread,
Sep 23, 2015, 8:38:47 AM9/23/15
to Alex Hall, swift-l...@googlegroups.com

> On 16 Sep 2015, at 17:59, Alex Hall <meh...@icloud.com> wrote:
>
>
>> On Sep 16, 2015, at 12:39, Jeremy Pereira <jeremy.j...@googlemail.com> wrote:
>>
>> To me it looks like it is as expected. The value type in the dictionary is Optional<String> The subscript return value is the value type of the dictionary wrapped in an Optional i.e. Optional<Optional<String>>
>>
>> Why would you expect anything else?
>
> As I said, I get the logic, I just thought I'd check. The way I learned it, an optional can have either a value or nil, which is the whole point of optionals. No one ever told me that the non-nil value in an optional can be another optional, so I figured it could be relied on to always be a non-optional. I'd never seen it before, and had never run across it in reading anything or talking to others about Swift, so I never expected it to work that way. Basically, I just didn't realize that Swift supports letting an optional be the non-nil value of an optional. I wanted to check to be sure it wasn't something odd, or that I wasn't doing something wrong.

Yes I can see your point of view, but I’ve always looked at Optional as just a type (in fact it is a simple generic enum with two cases) and some syntactic sugar which is why its actual behaviour came as no surprise to me.
Reply all
Reply to author
Forward
0 new messages