Methods in Chapel

Chapel supports methods defined on record types, which are similar to structs in other languages.

use IO;

record rect {
  var width, height: int;
}

// This `area` method has a receiver type of `rect`.
proc rect.area(): int {
  return this.width * this.height;
}

// Methods can be defined for either reference or value
// receiver types. Here's an example of a value receiver.
proc rect.perim(): int {
  return 2*this.width + 2*this.height;
}

proc main() {
  var r = new rect(width=10, height=5);

  // Here we call the 2 methods defined for our record.
  writeln("area: ", r.area());
  writeln("perim:", r.perim());

  // Chapel automatically handles method calls for both
  // value and reference types. You may want to use
  // a reference receiver type to avoid copying on method
  // calls or to allow the method to mutate the
  // receiving record.
  var rp = new shared rect(width=10, height=5);
  writeln("area: ", rp.area());
  writeln("perim:", rp.perim());
}

To run the program:

$ chpl methods.chpl -o methods
$ ./methods
area:  50
perim: 30
area:  50
perim: 30

In Chapel, records are value types by default, similar to structs in some other languages. Methods can be defined directly on these record types using the proc recordName.methodName() syntax.

The area and perim methods are defined on the rect record. In Chapel, the this keyword is used to refer to the current instance within a method, similar to self in some other languages.

Chapel doesn’t have a direct equivalent to pointer receivers, but it does have reference types. In the example, we use a shared keyword to create a reference-counted object, which is similar to using a pointer in some ways.

Chapel’s method calling syntax is the same for both value and reference types, so r.area() and rp.area() both work as expected.

Next, we’ll look at Chapel’s mechanism for grouping and naming related sets of methods: interfaces.