5.4 Closeable Objects
The Closeable interface has a single method, Closeable.close. A Closeable object can be used with the Closeable.let form, which automatically calls Closeable.close at the point where the binding goes out of scope. Port objects implement Closeable as does the TemporaryFile result of filesystem.make_temporary.
The first file example of Input and Output Ports can be written with Closeable.let like this, where the ports are automatically closed and the temporary file is automatically deleted:
> block:
Closeable.let outp = Port.Output.open_file(tmp.path, ~exists: #'truncate)
outp.write_bytes(#"data")
Closeable.let inp = Port.Input.open_file(tmp.path)
inp.read_bytes(4)
Bytes.copy(#"data")
The Closeable.let form is unusual in that it is a definition sequence macro, which receives all forms that follow the definition in a block context. The Closeable.let form moves those forms into a try close and adds a call to Closeable.let in a ~finally clause, so the close operation happens even if an error occurs the body after Closeable.let.
Beware that the right-hand side of a Closeable.let definition is evaluated with asynchronous breaks disabled. Disabling breaks reliably handles the case that, say, a user hits Ctl-C in a terminal running a Rhombus program. In that case, either the Closeable is has not opened, or it is opened and will be reliably closed when the exception triggered by Ctl-C is raised.