[swift-users] Detect if a generic type is numeric

Kevin Lundberg kevin at klundberg.com
Wed Oct 4 20:30:07 CDT 2017


Can you do something like this?

func isNumber<T: Numeric>(_ value: T) -> Bool { return true }

func isNumber<T>(_ value: T) -> Bool { return false }

I don't recall whether or not swift will pick the right version of the
function here, or whether this can even compile (mac isnt open at the
moment), but if you can overload functions in this way then it might be
much nicer than checking for lots of concrete types.


On 10/1/2017 6:27 PM, V T via swift-users wrote:
>
>
>> On 1. Oct 2017, at 22:43, davelist at mac.com <mailto:davelist at mac.com>
>> wrote:
>>
>>
>>
>>> On Oct 1, 2017, at 2:32 PM, Glenn L. Austin <glenn at austinsoft.com
>>> <mailto:glenn at austinsoft.com>> wrote:
>>>
>>>>
>>>> On Oct 1, 2017, at 8:56 AM, Dave Reed via swift-users
>>>> <swift-users at swift.org <mailto:swift-users at swift.org>> wrote:
>>>>
>>>>
>>>>> On Sep 21, 2017, at 3:58 PM, V T via swift-users
>>>>> <swift-users at swift.org <mailto:swift-users at swift.org>> wrote:
>>>>>
>>>>> Hi there!
>>>>>
>>>>> Is there a best way to check if a given type conforms to numeric
>>>>> protocol (Integer or FP) at runtime?
>>>>>
>>>>> func checkNumeric<T>(_ value: T) {
>>>>> /* return true if vaiue is Integer or FP */
>>>>> /* this will not compile: */
>>>>> if value is Numeric {
>>>>>
>>>>> }
>>>>> }
>>>>>
>>>>> Best regards!
>>>>>
>>>>> VT
>>>>>
>>>>
>>>> I think the way to do it is to try casting as the type, but you
>>>> can't use "as? Numeric" as you get:
>>>>
>>>> error: protocol 'Numeric' can only be used as a generic constraint
>>>> because it has Self or associated type requirements
>>>>
>>>> but you could check for each specific numeric type such as:
>>>>
>>>> func checkNumeric<T>(_ value: T) {
>>>>   if (value as? Int != nil) || (value as? Float != nil) {
>>>>       print("numeric")
>>>>   } else {
>>>>       print("not numeric")
>>>>   }
>>>> }
>>>>
>>>> checkNumeric(3)
>>>> checkNumeric(3.0)
>>>> checkNumeric("3")
>>>
>>> You can also use the 'is' operator, as in 'value is Int || value is
>>> Float || value is Double'
>>>
>>> -- 
>>> Glenn L. Austin, Computer Wizard, AustinSoft.com <http://AustinSoft.com>
>>
>>
>> Ah, I had forgotten "is" works in Swift
>>
>> Just be careful as:
>>
>> func checkNumeric<T>(_ value: T) {
>>    if (value is Int) || (value is Float) {
>>        print("numeric")
>>    } else {
>>        print("not numeric")
>>    }
>> }
>>
>
> Thanks all! My current implementation looks like this. A bit
> redundant, bat it works. My intention was to simplify that monster:
>
> func isNumber<T>(_ value: T) -> Bool {
>     let valueMirror = Mirror(reflecting: value)
>     #ifarch(arm) || arch(arm64)
>         if (valueMirror.subjectType == Int.self ||
> valueMirror.subjectType == UInt.self || valueMirror.subjectType ==
> Double.self || valueMirror.subjectType == Int8.self ||
> valueMirror.subjectType == Int16.self || valueMirror.subjectType ==
> Int32.self || valueMirror.subjectType == Int64.self ||
> valueMirror.subjectType == UInt8.self || valueMirror.subjectType ==
> UInt16.self || valueMirror.subjectType == UInt32.self ||
> valueMirror.subjectType == UInt64.self || valueMirror.subjectType ==
> Float.self || valueMirror.subjectType == Float32.self ||
> valueMirror.subjectType == NSNumber.self || valueMirror.subjectType ==
> NSDecimalNumber.self ) {
>             return true
>         }
>         else {
>             return false
>         }
>     #else
>         if (valueMirror.subjectType == Int.self ||
> valueMirror.subjectType == UInt.self || valueMirror.subjectType ==
> Double.self || valueMirror.subjectType == Int8.self ||
> valueMirror.subjectType == Int16.self || valueMirror.subjectType ==
> Int32.self || valueMirror.subjectType == Int64.self ||
> valueMirror.subjectType == UInt8.self || valueMirror.subjectType ==
> UInt16.self || valueMirror.subjectType == UInt32.self ||
> valueMirror.subjectType == UInt64.self || valueMirror.subjectType ==
> Float.self || valueMirror.subjectType == Float32.self ||
> valueMirror.subjectType == Float80.self || valueMirror.subjectType ==
> NSNumber.self || valueMirror.subjectType == NSDecimalNumber.self ) {
>             return true
>         }
>         else {
>             return false
>         }
>     #endif
> }
>
>> checkNumeric(3)
>> checkNumeric(3.0)
>> checkNumeric("3")
>>
>> outputs:
>>
>> numeric
>> not numeric
>> not numeric
>>
>> Since the literal 3.0 is a Double so you'd have to catch every
>> floating point type (including CGFloat, I suspect etc.) vs. just
>> trying to cast to a Float (although I guess casting to a Float could
>> have unexpected results also if someone made an extension that allows
>> a type to be cast as a Float).
>>
>> Dave
>>
>>
>
>
>
> _______________________________________________
> swift-users mailing list
> swift-users at swift.org
> https://lists.swift.org/mailman/listinfo/swift-users

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20171004/b17bc675/attachment.html>


More information about the swift-users mailing list