Generics allow you to write flexible, reusable functions and types that can work with any data type that conforms to a specific protocol or type constraints. This enables you to perform operations on multiple types without sacrificing type safety.

func additionUsingGeneric<T: Numeric>(n1: T, n2: T) -> T {
  return n1 + n2
}

let generic1 = additionUsingGeneric(n1: 23, n2: 23)
let generic2 = additionUsingGeneric(n1: 23, n2: 10.5)
print(generic1)
print(generic2)

Output:

46 33.5

Also push and pop can be used to add and remove values

Using generic as a stack

prin(getData())
func Addition<T>{
  var items = [Element]()
  
  mutating func push(_ item: Element){
    items.append(item)
  }
  
  mutating func pop() -> Double{
    return items.removeLast()
  }
}

func getData() {
  var add = Addition<Double>()
  add.push(8.16)
  add.push(12)
  print(add)
  
  let pop = add.pop()
  print(add)
  add.push(100)
  print(add)
}