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.