Pyro

A dynamically-typed, garbage-collected scripting language.

Version 0.19.2

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.