With Blocks
You can use a with
block to ensure that clean-up code gets run, even if the code inside the with
block panics or returns early.
File objects have builtin support for with
blocks, e.g.
with file = $file("data.txt") { do_stuff(); }
The file object's close()
method will be called when the with
block exits, even if the code inside the with
block panics or returns early.
Syntax
with
blocks have the following syntax:
with <name> = <expression> { ... }
Inside the with
block, <name>
is a new local variable.
If the value of <expression>
has an $end_with()
method, this method will be called when the with
block exits, even if the code inside the with
block panics or exits early via a break
, continue
, or return
statement.
Custom Classes
You can add support for with
blocks to any object by defining an $end_with()
method.
As an example, let's create a custom wrapper for writable files:
class WriteableFile { var file; def $init(path) { self.file = $file(path, "w"); } def $end_with() { self.file:close(); } pub def write(arg) { self.file:write(arg); } }
Here the $end_with()
method ensures that the file will be closed when the with
block exits, even if the code inside the with
block panics or returns early.
We can use our custom WriteableFile
type like this:
with file = WriteableFile("data.txt") { file:write("foo"); file:write("bar"); file:write(function_that_might_panic()); }
The with
block ensures that the file will be closed even if function_that_might_panic()
panics.
In practice, Pyro's file
type already has builtin support for with
blocks so this kind of wrapper is unnecessary, but you can implement similar support for your own types.
Variable Scoping
You can use a with
block as a scoping mechanism to define an explicit, limited scope for a variable declaration, e.g.
var foo = 123; with foo = 456 { assert foo == 456; } assert foo == 123;
Inside the with
block, foo
is a new local variable with lexical scope.
This is equivalent to wrapping the variable declaration in a {}
block, e.g.
var foo = 123; { var foo = 456; assert foo == 456; } assert foo == 123;
You can use unpacking syntax for variable declarations in with
blocks, e.g.
with (foo, bar) = $tup(123, 456) { assert foo == 123; assert bar == 456; }
The variables foo
and bar
are new local variables defined inside the with
block.