Pyro

A dynamically-typed, garbage-collected scripting language.

Version 0.21.0

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") {
    ...
}

Here, the with block ensures that 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. You don't need to explicitly call close() on the file object yourself.

Syntax

with blocks have the following syntax:

with <name> = <expression> {
    ...
}

Custom Classes

You can add support for with blocks to any object by defining $enter() and/or $exit() methods.

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 $exit() {
        self.file:close();
    }

    pub def write(arg) {
        self.file:write(arg);
    }
}

Here the $exit() 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 also 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;

Using a with block in this case just makes the limited scope of the variable more explicit.

Note that 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.