Please consider the following code:

let myString: String? = "Hello"
let anyValue: Any = myString
let obj: AnyObject? = anyValue as? AnyObject // nil, since it's 
Optional<String>, String being struct,
                                         // no implicit bridge to AnyObject. 
(myString as AnyObject will
                                         // create _NSContiguousString).

if let optionalAny: AnyObject? = anyValue as? AnyObject? { // Error - can't 
downcast from Any
    // ...
}

if let optionalAny: AnyObject? = anyValue as? AnyObject { // nil
    // ...
}

if let optionalAny: AnyObject? = asOpt(anyValue) { // Optional<AnyObject>
    if let value = optionalAny { // value is _NSContiguousString
        value.dynamicType
    }
}

This behavior is IMHO incosistent at best. Should this be considered correct 
behavior or a compiler bug?

> On Jun 22, 2016, at 5:59 PM, L. Mihalkovic <[email protected]> 
> wrote:
> 
> 
> 
> On Jun 22, 2016, at 5:51 PM, John McCall <[email protected] 
> <mailto:[email protected]>> wrote:
> 
>> 
>>> On Jun 22, 2016, at 12:15 AM, L. Mihalkovic via swift-evolution 
>>> <[email protected] <mailto:[email protected]>> wrote:
>>> 
>>> Func asOpt<T>(v:Any) -> Optional<T> {
>>>   If let val = v as? T {
>>>     Return val
>>>   }
>>>   Return nil
>>> }
>>> Regards
>>> LM
>>> (From mobile)
>> 
>> This is just:
>>   return v as? T
> 
> Had more code where i took it from... I thk it is one of these simple thgs 
> that u never forget but may not be immediate to thk abt. Maybe worth adding 
> to doc comment for Optional<> (forgive if is there already)
> 
>> 
>> John.
>> 
>>> 
>>> On Jun 22, 2016, at 7:11 AM, Charlie Monroe via swift-evolution 
>>> <[email protected] <mailto:[email protected]>> wrote:
>>> 
>>>> Unfortunately, this is not as easy, because automatic bridging won't be 
>>>> applied:
>>>> 
>>>> let myString: String? = "Hello"
>>>> let anyValue: Any = myString
>>>> 
>>>> myString as? AnyObject // _NSContiguousString
>>>> anyValue as? AnyObject // nil, since String is struct
>>>> 
>>>> let array: [String]? = ["Hello"]
>>>> let anyArray: Any = array
>>>> anyArray as? AnyObject // nil
>>>> anyArray as? [AnyObject] // nil
>>>> array as? AnyObject // ["Hello"]
>>>> 
>>>> And this goes for strings, arrays, dictionaries and possibly other types. 
>>>> Which means that you need to handle manually all of the bridging to ObjC 
>>>> types, which has really grown in Swift 3, taking into account all the 
>>>> Foundation types that are now structs.
>>>> 
>>>> Should this then be considered compiler bug that bridging isn't taken into 
>>>> account?
>>>> 
>>>> Nevertheless, I'd still find it useful exposing the isOptional() function 
>>>> as well as the asOptional which would allow a cast from Any to 
>>>> Optional<Any> which is not possible at all at this moment since any such 
>>>> cast will pick up the Optional first:
>>>> 
>>>> let myString: String? = "Hello"
>>>> let anyValue: Any = myString
>>>> if let value = anyValue as? Any {
>>>>     value.dynamicType // This is still Optional<String>, not naively just 
>>>> the value of the optional
>>>> }
>>>> 
>>>> 
>>>> 
>>>>> On Jun 21, 2016, at 8:18 PM, Joe Groff <[email protected] 
>>>>> <mailto:[email protected]>> wrote:
>>>>> 
>>>>> 'as?' should already do this. If you have an Any that contains an 
>>>>> Optional<T> and cast 'any as? T', you'll get the value inside the 
>>>>> Optional if there is one, or the cast will fail if the optional is nil or 
>>>>> the type doesn't match.
>>>>> 
>>>>> -Joe
>>>>> 
>>>>>> On Jun 20, 2016, at 11:00 PM, Charlie Monroe via swift-evolution 
>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>> 
>>>>>> I've recently written a CoreData editor on iOS which automatically 
>>>>>> generates UI based on the model which is described using classes such as 
>>>>>> PrimitiveProperty, etc. Since it automatically sets the value on the 
>>>>>> entity, it needs to convert the value to AnyObject in order to pass it 
>>>>>> to setValue(_:forKey:), so it needs to be able to detect whether the 
>>>>>> value is Optional and in case it is, either transform the non-nil value 
>>>>>> to AnyObject (String -> NSString, Array -> NSArray, ...). Which is 
>>>>>> currently really hard to achieve: 
>>>>>> 
>>>>>> var obj: IndexPath? = IndexPath()
>>>>>> let anyValue: Any = obj
>>>>>> anyValue.dynamicType /// Optional<Foundation.IndexPath>.Type
>>>>>> 
>>>>>> /// Using only anyValue, determine if it's Optional and retrieve its 
>>>>>> value if 
>>>>>> /// non-nil as AnyObject.
>>>>>> func isOptional(anyValue: Any) -> Bool {
>>>>>>    // Error: Cannot downcast from 'Any' (aka 'protocol<>') to a more 
>>>>>>    // optional type 'Optional<_>'
>>>>>>    return anyValue is Optional
>>>>>>    return anyValue as? Optional != nil
>>>>>>    ...
>>>>>> }
>>>>>> 
>>>>>> Unless there are major reasons why it's not exposed, I'd propose 
>>>>>> introducing a new function isOptional(anyValue: Any) -> Bool, which 
>>>>>> would simply call Builtin.isOptional just like _isOptional does in 
>>>>>> Builtin.swift. (which pretty much is just taking the current 
>>>>>> _isOptional, removing underscore and marking it public).
>>>>>> 
>>>>>> However, this still doesn't help with the issue of retrieving the value 
>>>>>> of the Optional. You now know the value in `anyValue` is Optional, but 
>>>>>> there is no good way to cast it to e.g. Optional<AnyObject>. Here we're 
>>>>>> getting into a vicious cycle that Any can be an Optional which is Any.
>>>>>> 
>>>>>> My second part of the proposal introduces another function:
>>>>>> 
>>>>>> func asOptional<T>(anyValue: Any) -> Optional<T>?
>>>>>> 
>>>>>> Which will:
>>>>>> - return nil if !isOptional(anyValue)
>>>>>> - return a non-nil value only if `anyValue` contains in fact an Optional 
>>>>>> of type T.
>>>>>> 
>>>>>> Usage:
>>>>>> 
>>>>>> if let anyObjOptional: AnyObject? = asOptional(anyValue: anyValue) {
>>>>>>    if let anyObj = anyObjOptional {
>>>>>>        // anyObj is now the actual content of the optional.
>>>>>>    }
>>>>>> }
>>>>>> 
>>>>>> As a sidenote, this is my current workaround:
>>>>>> 
>>>>>> private protocol _XUOptional {
>>>>>>    var objectValue: AnyObject? { get }
>>>>>> }
>>>>>> 
>>>>>> extension Optional: _XUOptional {
>>>>>>    var objectValue: AnyObject? {
>>>>>>        switch self {
>>>>>>        case .None:
>>>>>>            return nil
>>>>>>        case .Some(_):
>>>>>>            return self! as? AnyObject
>>>>>>        }
>>>>>>    }
>>>>>> }
>>>>>> 
>>>>>> if let optional = anyValue as? _XUOptional {
>>>>>>    let object = optional.objectValue
>>>>>>    /// ...
>>>>>> }
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> _______________________________________________
>>>>>> swift-evolution mailing list
>>>>>> [email protected] <mailto:[email protected]>
>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>>>> 
>>>> 
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> [email protected] <mailto:[email protected]>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>> _______________________________________________
>>> swift-evolution mailing list
>>> [email protected] <mailto:[email protected]>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to