MoonBit Language Tour MoonBit

Generics and Functions

Generics allow you to write one set of code for many different types without repeating similar logic.

In the example, separate functions swap_int and swap_bool are defined for Array[Int] and Array[Bool]. If we also wanted to swap elements in Array[String] or Array[Char], we have to write two more similar functions. It would be better if the type could be chosen and passed by the caller, like a function parameter.

MoonBit provides generics for this. Generic parameters are enclosed in [], and you can define multiple of them. For functions, generic parameters appear after the keyword fn. In the example, the function swap defines one generic parameter T, and T is used twice in the function definition:

  • As the element type of the parameter arr: arr : Array[T]
  • As the type of the local variable tmp: let tmp : T = arr[0]

Thus, the elements in the array and the variable tmp share the same type T, and the caller decides what T is. When calling in main, type inference can deduce the concrete type of T from the argument array, so there is no need to pass type arguments explicitly.

Explicitly specifying generic parameter types

In most function calls, type inference can determine the generic parameter types, so MoonBit does not provide a syntax for explicitly passing them like some other languages do. If you want to specify them explicitly, you can add additional type annotations, for example:

swap(([1, 2] : Array[Int]))

or

let arr : Array[Int] = [1, 2]
swap(arr)
///|
/// swap two int in array
fn swap_int(arr : Array[Int]) -> Unit {
  let tmp : Int = arr[0]
  arr[0] = arr[1]
  arr[1] = tmp
}

///|
/// swap two bool in array
fn swap_bool(arr : Array[Bool]) -> Unit {
  let tmp : Bool = arr[0]
  arr[0] = arr[1]
  arr[1] = tmp
}

///|
/// generic swap
fn[T] swap(arr : Array[T]) -> Unit {
  let tmp : T = arr[0]
  arr[0] = arr[1]
  arr[1] = tmp
}

///|
fn main {
  // swap ints
  let array1 = [1, 2]
  swap_int(array1)
  println(array1)

  // swap bools
  let array2 = [true, false]
  swap_bool(array2)
  println(array2)

  // generic swap
  swap(array1)
  swap(array2)
  println(array1)
  println(array2)
}