Generics in Chapel

Chapel supports generic programming through its concept of “where clauses” and type parameters. Let’s explore how to implement generic functions and types in Chapel.

First, let’s create a generic function similar to the SlicesIndex function:

proc slicesIndex(arr, v) where arr: [] ?eltType, v: eltType {
  for i in arr.domain {
    if arr[i] == v {
      return i;
    }
  }
  return -1;
}

This function takes an array arr and a value v, and returns the index of the first occurrence of v in arr, or -1 if not present. The where clause specifies that arr must be an array of some type eltType, and v must be of the same type.

Now, let’s create a generic linked list type:

class List {
  type eltType;
  var head, tail: unmanaged Node(eltType)?;

  proc push(v: eltType) {
    var newNode = new unmanaged Node(eltType, v);
    if tail == nil {
      head = tail = newNode;
    } else {
      tail!.next = newNode;
      tail = newNode;
    }
  }

  iter these(): eltType {
    var current = head;
    while current != nil {
      yield current!.val;
      current = current!.next;
    }
  }
}

class Node {
  type eltType;
  var val: eltType;
  var next: unmanaged Node(eltType)?;

  proc init(type eltType, val: eltType) {
    this.eltType = eltType;
    this.val = val;
  }
}

In this implementation, List is a generic class that can hold elements of any type. The push method adds elements to the list, and the these iterator allows for easy iteration over the list elements.

Now let’s use these generic constructs:

proc main() {
  var s = ["foo", "bar", "zoo"];
  writeln("index of zoo: ", slicesIndex(s, "zoo"));

  var lst = new List(int);
  lst.push(10);
  lst.push(13);
  lst.push(23);
  
  write("list: ");
  for elem in lst {
    write(elem, " ");
  }
  writeln();

  delete lst;
}

In this main function, we first demonstrate the use of the slicesIndex function with an array of strings. Then, we create a List of integers, push some values onto it, and iterate over its elements.

To run this program, save it to a file (e.g., generics.chpl) and use the Chapel compiler:

$ chpl generics.chpl -o generics
$ ./generics
index of zoo: 2
list: 10 13 23 

Chapel’s approach to generics allows for type-safe, reusable code. The where clauses and type parameters provide a powerful way to express constraints and create generic functions and types.