Normally in guard and if condition lists, you look up a value in a dictionary 
and conditionally cast:

    if let value = dict[key] as? T, ...

The "as?" operator passes the Any? type through, and the lhs result is T, not 
T?.

* dict[key] returns Any?
* Any? as T returns T?, not T??
* the conditional binding binds T? to T
* PROFIT!

However, this (somewhat illogical) "sugar" doesn't happen when you 
conditionally cast T? to U, for example, when a dictionary is [AnyHashable: 
String]:

guard let value = dict["Key"] as? NSString
    else { fatalError() }

(see http://i.imgur.com/SkXkk6o.jpg <http://i.imgur.com/SkXkk6o.jpg>)

* dict[key] returns String?
* String? as T is guaranteed to fail

In this case, the compiler asserts that a cast from String? to an unrelated 
type NSString always fails. You can mitigate this by sticking an "Any" cast in 
the middle:

guard let value = dict["Key"] as Any as? NSString
    else { fatalError() }

If that's not "magic", I don't know what is.  (You can also cast the dictionary 
to [AnyHashable: NSString], etc.)

Jack L's initial response: "oh, that's a weird bridging edge case 😕 it seems 
like we should just make that work..."  
http://twitter.com/_jackhl/status/784998768898744320 
<http://twitter.com/_jackhl/status/784998768898744320>) but he asked me to 
follow up here on SwiftEv. It seems to me that in conditional binding with 
conditional casting, you're asking the compiler to do not one but *two* magical 
things:

1. Apply what *looks* like assignment (I have a similar issue with if 
case/guard case) but is actually something else
2. Apply what *looks* like conditional casting but which magically passes Any? 
through to T?, not T??

I handwave this (but just the moment) and say "it's not really an assignment, 
so it's not really a conditional cast". Jack asked me to bring this discussion 
over to Swift Evolution and ask the greater community whether Swift is doing 
these things right, and if not, how it should fix them. 

Where I stand:

* If there's going to be magic, it should be documented (and it is not) in the 
Swift Programming Language
* If there's going to be magic, it should work for T?, not just Any?
* I'd rather there not be magic here

-- E
p.s. I'd also rather that if-case/guard-case would use ":" like in switch 
statements not "=", but no one seems to be responding to that thread, dagnabit
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to