Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add OR condition in Swift generic where clause?

I am extending SCNVector3 from Apple SceneKit with arithmetic operations with a number. I use generic for the number's type, but I have found out that I have to write at least two versions of each function, as this does not work:

extension SCNVector3 {
    static func *<T> (left: SCNVector3, right: T) -> SCNVector3 {
        return SCNVector3(left.x * Float(right), left.y * Float(right), left.z * Float(right))
}

and gives error Cannot invoke initializer for Type 'Float' with an argument list of type '(T)'

Looking at definition of Float in Apple documentation, I see that the most generic I can get is init<Source: BinaryFloatingPoint> or init<Source: BinaryInteger>.

So I have to rewrite the extension as following, making two almost identical functions for each operation:

extension SCNVector3 {
    static func *<T> (left: SCNVector3, right: T) -> SCNVector3 where T: BinaryFloatingPoint {
        return SCNVector3(left.x * Float(right), left.y * Float(right), left.z * Float(right))

    static func *<T> (left: SCNVector3, right: T) -> SCNVector3 where T: BinaryInteger {
        return SCNVector3(left.x * Float(right), left.y * Float(right), left.z * Float(right))
}

I can place AND in where clause — by having two conditions after where separated by a comma.

But is there any way I can place OR there?

like image 437
Denis Bystruev Avatar asked Jun 10 '18 10:06

Denis Bystruev


People also ask

How do you declare a generic variable in Swift?

Generics allow you to declare a variable which, on execution, may be assigned to a set of types defined by us. In Swift, an array can hold data of any type. If we need an array of integers, strings, or floats, we can create one with the Swift standard library.

How do you write a generic function in Swift?

Swift Generic Function In Swift, we can create a function that can be used with any type of data. Such a function is known as a Generic Function. Here's how we can create a generic function in Swift: // create a generic function func displayData<T>(data: T){ ... }

What is a generic type parameter?

Generic Methods A type parameter, also known as a type variable, is an identifier that specifies a generic type name. The type parameters can be used to declare the return type and act as placeholders for the types of the arguments passed to the generic method, which are known as actual type arguments.

What is generic constraints in Swift?

Generic Where Clauses Type constraints, as described in Type Constraints, enable you to define requirements on the type parameters associated with a generic function, subscript, or type. It can also be useful to define requirements for associated types. You do this by defining a generic where clause.


1 Answers

Your basic implementation should start by this:

extension SCNVector3 {
    static func * (vector: SCNVector3, scale: Float) -> SCNVector3 {
        return SCNVector3(vector.x * scale, vector.y * scale, vector.z * scale)
    }
}

The vector has Float components therefore you should always multiplicate only by a Float. That's how all operators in Swift work. If you have a different type, cast it before multiplicating, not as a side-effect of multiplication.

If you really want to pass other types, then you can use method overloading:

extension SCNVector3 {
    static func *<T> (left: SCNVector3, right: T) -> SCNVector3 where T: BinaryFloatingPoint {
        return left * Float(right)
    }

    static func *<T> (left: SCNVector3, right: T) -> SCNVector3 where T: BinaryInteger {
        return left * Float(right)
    }
}

There is no way how to define or in types.

like image 177
Sulthan Avatar answered Sep 18 '22 19:09

Sulthan