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

V T not_my_name+swift at mailbox.org
Sun Oct 1 17:27:05 CDT 2017



> On 1. Oct 2017, at 22:43, davelist at mac.com wrote:
> 
> 
> 
>> On Oct 1, 2017, at 2:32 PM, Glenn L. Austin <glenn at austinsoft.com> wrote:
>> 
>>> 
>>> On Oct 1, 2017, at 8:56 AM, Dave Reed via swift-users <swift-users at swift.org> wrote:
>>> 
>>> 
>>>> On Sep 21, 2017, at 3:58 PM, V T via swift-users <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
> 
> 
> 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)
    #if arch(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
> 
> 

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


More information about the swift-users mailing list