Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What protocol should be adopted by a Type for a generic function to take any number type as an argument in Swift?

I want to make a function accept any number (Int, Float, Double, ...) in Swift

func myFunction <T : "What to put here"> (number : T) ->  {     //... } 

without using NSNumber

like image 420
ielyamani Avatar asked Aug 29 '14 20:08

ielyamani


People also ask

How do you make a generic function in Swift?

Example: Swift Generic Function In the above example, we have created a generic function named displayData() with the type parameter <T> . we have passed a string value, so the placeholder parameter T is automatically replaced by String . the placeholder is replaced by Int .

What is generic protocol in Swift?

Swift enables us to create generic types, protocols, and functions, that aren't tied to any specific concrete type — but can instead be used with any type that meets a given set of requirements.

What are protocols used for in Swift?

Protocol is a very powerful feature of the Swift programming language. Protocols are used to define a “blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality.”

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.


1 Answers

Update: The answer below still applies in principle, but Swift 4 completed a redesign of the numeric protocols, such that adding your own is often unnecessary. Take a look at the standard library's numeric protocols before you build your own system.


This actually isn't possible out of the box in Swift. To do this you'll need to create a new protocol, declared with whatever methods and operators you're going to use inside your generic function. This process will work for you, but the exact details will depend a little on what your generic function does. Here's how you'd do it for a function that gets a number n and returns (n - 1)^2.

First, define your protocol, with the operators and an initializer that takes an Int (that's so we can subtract one).

protocol NumericType {     func +(lhs: Self, rhs: Self) -> Self     func -(lhs: Self, rhs: Self) -> Self     func *(lhs: Self, rhs: Self) -> Self     func /(lhs: Self, rhs: Self) -> Self     func %(lhs: Self, rhs: Self) -> Self     init(_ v: Int) } 

All of the numeric types already implement these, but at this point the compiler doesn't know that they conform to the new NumericType protocol. You have to make this explicit -- Apple calls this "declaring protocol adoption with an extension." We'll do this for Double, Float, and all the integer types:

extension Double : NumericType { } extension Float  : NumericType { } extension Int    : NumericType { } extension Int8   : NumericType { } extension Int16  : NumericType { } extension Int32  : NumericType { } extension Int64  : NumericType { } extension UInt   : NumericType { } extension UInt8  : NumericType { } extension UInt16 : NumericType { } extension UInt32 : NumericType { } extension UInt64 : NumericType { } 

Now we can write our actual function, using the NumericType protocol as a generic constraint.

func minusOneSquared<T : NumericType> (number : T) -> T {     let minusOne = number - T(1)     return minusOne * minusOne }  minusOneSquared(5)              // 16 minusOneSquared(2.3)            // 1.69 minusOneSquared(2 as UInt64)    // 1 
like image 145
Nate Cook Avatar answered Sep 23 '22 17:09

Nate Cook