ChapelIO

Note

All Chapel programs automatically use this module by default. An explicit use statement is not necessary.

Basic types and utilities in support of I/O operation.

Most of Chapel’s I/O support is within the IO module. This section describes automatically included basic types and routines that support the IO module.

Writing

The writeln function allows for a simple implementation of a Hello World program:

writeln("Hello, World!");
// outputs
// Hello, World!

The readThis(), writeThis(), and readWriteThis() Methods

When programming the input and output method for a custom data type, it is often useful to define both the read and write routines at the same time. That is possible to do in a Chapel program by defining a readWriteThis method, which is a generic method expecting a single channel argument.

In cases when the reading routine and the writing routine are more naturally separate, or in which only one should be defined, a Chapel program can define readThis (taking in a single argument - a readable channel) and/or writeThis (taking in a single argument - a writeable channel).

If none of these routines are provided, a default version of readThis and writeThis will be generated by the compiler. If readWriteThis is defined, the compiler will generate readThis or writeThis methods - if they do not already exist - which call readWriteThis.

Note that arguments to readThis and writeThis may represent a locked channel; as a result, calling methods on the channel in parallel from within a readThis, writeThis, or readWriteThis may cause undefined behavior. Additionally, performing I/O on a global channel that is the same channel as the one readThis, writeThis, or readWriteThis is operating on can result in a deadlock. In particular, these methods should not refer to stdin, stdout, or stderr explicitly or implicitly (such as by calling the global writeln function). Instead, these methods should only perform I/O on the channel passed as an argument.

Because it is often more convenient to use an operator for I/O, instead of writing

f.readwrite(x);
f.readwrite(y);

one can write

f <~> x <~> y;

Note that the types IO.ioLiteral and IO.ioNewline may be useful when using the <~> operator. IO.ioLiteral represents some string that must be read or written as-is (e.g. "," when working with a tuple), and IO.ioNewline will emit a newline when writing but skip to and consume a newline when reading.

This example defines a readWriteThis method and demonstrates how <~> will call the read or write routine, depending on the situation.

class IntPair {
  var x: int;
  var y: int;
  proc readWriteThis(f) throws {
    f <~> x <~> new ioLiteral(",") <~> y <~> new ioNewline();
  }
}
var ip = new IntPair(17,2);
write(ip);
// prints out
// 17,2

delete ip;

This example defines a only a writeThis method - so that there will be a function resolution error if the class NoRead is read.

class NoRead {
  var x: int;
  var y: int;
  proc writeThis(f) throws {
    f <~> "hello";
  }
  // Note that no readThis function will be generated.
}
var nr = new NoRead();
write(nr);
// prints out
// hello

// Note that read(nr) will generate a compiler error.

delete nr;

Default writeThis and readThis Methods

Default writeThis methods are created for all types for which a user-defined writeThis or readWriteThis method is not provided. They have the following semantics:

  • for a class: outputs the values within the fields of the class prefixed by the name of the field and the character =. Each field is separated by a comma. The output is delimited by { and }.

  • for a record: outputs the values within the fields of the class prefixed by the name of the field and the character =. Each field is separated by a comma. The output is delimited by ( and ).

Default readThis methods are created for all types for which a user-defined readThis method is not provided. The default readThis methods are defined to read in the output of the default writeThis method.

Additionally, the Chapel implementation includes writeThis methods for built-in types as follows:

  • for an array: outputs the elements of the array in row-major order where rows are separated by line-feeds and blank lines are used to separate other dimensions.

  • for a domain: outputs the dimensions of the domain enclosed by { and }.

  • for a range: output the lower bound of the range, output .., then output the upper bound of the range. If the stride of the range is not 1, output the word by and then the stride of the range. If the range has special alignment, output the word align and then the alignment.

  • for tuples, outputs the components of the tuple in order delimited by ( and ), and separated by commas.

These types also include readThis methods to read the corresponding format. Note that when reading an array, the domain of the array must be set up appropriately before the elements can be read.

Note

Note that it is not currently possible to read and write circular data structures with these mechanisms.

proc write(const args ...?n)

Equivalent to try! stdout.write. See IO.channel.write

proc writeln(const args ...?n)

Equivalent to try! stdout.writeln. See IO.channel.writeln

proc writef(fmt: ?t, const args ...?k): bool

Equivalent to try! stdout.writef. See FormattedIO.channel.writef.