Nice!

Would you consider this as something that should be part of the language? IMHO 
working this out takes much more time than it should and these two functions 
would definitely help out a lot.

> On Jun 22, 2016, at 9:15 AM, L. Mihalkovic <laurent.mihalko...@gmail.com> 
> wrote:
> 
> Func asOpt<T>(v:Any) -> Optional<T> {
>   If let val = v as? T {
>     Return val
>   }
>   Return nil
> }
> Regards
> LM
> (From mobile)
> 
> On Jun 22, 2016, at 7:11 AM, Charlie Monroe via swift-evolution 
> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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 <jgr...@apple.com 
>>> <mailto:jgr...@apple.com>> 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 
>>>> <swift-evolution@swift.org <mailto:evolut...@swift.org>> 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
>>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>> 
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>

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

Reply via email to