Vote on context manager syntax!

Hi Chapel community!

We want to add the context management statement to the language.
Over in this GitHub issue there's been some discussion about what
the syntax for context managers should look like, and we're currently
trying to settle on one of two forms:

// This form looks similar to the Python syntax that inspired it:
manage myManager() as myResource do
  myResource.doSomething();
// This form flips the order of the manager and resource:
manage myResource from myManager() do
  myResource.doSomething();

If you know what context managers are and have a preference for one of
the two forms above, feel free to leave a comment and a vote here!


The context manager statement comes from Python. It provides a way to
perform setup and teardown actions at the beginning and end of a
block with minimal boilerplate.

Here's what the statement looks like in Python:

with myManager() as myResource:
  myResource.doSomething()

The syntax can be read as "with expression as identifier". The
myManager() expression following the with keyword returns a value
that is known as the "manager". The statement proceeds by calling a
special method called __enter__ on the manager. This method
may make some state changes, and then optionally return a resource.
The name myResource is used to refer to the "resource" returned by
__enter__ within the scope of the block.

When the managed block is exited, the statement will call __exit__
on the manager to let the manager perform any teardown actions. The
__exit__ method takes special arguments that let it interact nicely
with Python's exception handling.

A more detailed explanation of Python context managers can be read
here: 27. Context Managers — Python Tips 0.1 documentation

Context managers can be used to cleanly abstract a variety of different
patterns. [Note, the following examples are Chapel code using Python
syntax in order to avoid bias towards one of the syntax styles above.
We don't currently intend to adapt the Python syntax directly. None of
these examples work today.]

They can be used to automatically close a file at the end of
a block:

with open('file.txt', 'w') as myFile {
  myFile.write('Hello!');
}
// The file is automatically closed when the block exits.

They can be used to time certain blocks of code:

var t = new Timer();
with t {
  someExpensiveComputation1();
  someExpensiveComputation2();
}
// The time spent executing the block is printed.
writeln(t.elapsed());

They can be used to protect certain resources with a lock:

var guardedInt = new MutexGuard(int);
forall i in 1..3 do
  // Lock the mutex and get an exclusive ref to the int.
  with guardedInt as x do
    x += i;
writeln(guardedInt.nonLockingRead());
// This should print '6'.

As well as many other clever and creative patterns that can
be used to make developer lives easier.