Guard Protocol

Like many other subsystems in Monte, guards can be made from any ordinary object which implements the correct methods.

The Basics

The main method for a guard is coerce/2, which takes an object to examine, called the specimen, and an ejector. If the specimen conforms to the guard, then the guard returns the conformed value; otherwise, the ejector is used to abort the computation.

object Any:
    to coerce(specimen, _):
        return specimen

object Void:
    to coerce(_, _):
        return null

Here are two example guards, Any and Void. Any passes all specimens through as-is, and Void ignores the specimen entirely, always returning null.

Here’s an actual test. The Empty guard checks its specimen, which is a container, for emptiness and ejects on failure:

object Empty:
    to coerce(specimen, ej):
        if (specimen.size() != 0):
            throw.eject(ej, `$specimen was not empty`)

The ejector does not need to have a meaningful object (nor even a string) as its payload, but the payload may be used for diagnostic purposes by the runtime. For example, a debugger might display them to a developer, or a debugging feature of the runtime might record them to a log.

Unretractable Guards

Informally, an unretractable guard cannot be fooled by impostor objects that only pretend to be guarded, and it also will not change its mind about an object on two different coercions.

Formally, an unretractable guard Un is a guard such that for all Monte objects o, if o is successfully coerced by Un, then it will always be successfully coerced by Un, regardless of the internal state of Un or o.