The local operator in perl is an indispensable tool for developing exception-safe code, but it has two major limitations:
polymake has two extensions allowing to overcome these limitations:
There are also localization functions for the most popular operations on scalars and arrays, which sometimes need to be reverted in an exception-safe manner:
An object of the class Poly::Scope can be used to define a localization scope different from the default (the enclosing lexical scope.)
All localized updates made between begin_locals and end_locals survive the end of the lexical scope, they are reverted only when the object pointed by $scope is being destroyed. As shown in the example, you can use both standard local operators and the local_* functions described above. One Poly::Scope object can be used to gather the localizations several times.
The object of the class Poly::Scope serves also another purpose: it has two queues for descriptors of different deferred activities. Later on the object may be asked to run all the collected activities. You can see this as an extension of the END subroutine concept.
Register some action for later execution. The deferred queue is activated when the $scope->perform_deferred method is called. The cleanup queue is activated during the destruction of the $scope object itself; it is intended for exception-safe cleanup operations, just as the name suggests.
KEY in the deferred queue can be an arbitrary string identifying the action. To avoid conflicts, different packages should use their names as prefixes in the key, unless it is purposely shared.
KEY in the cleanup queue should be the reference to the object subject to clean.
ACTION is a descriptor, containing all necessary information to perform the action. The following data formats are supported:
ACTION is ... | operation performed |
---|---|
code reference | code->(KEY) |
object reference | object->proceed(KEY) (in deferred) |
object->cleanup(KEY) (in cleanup) | |
[ arguments, ... ] | KEY->proceed(arguments) (in deferred) |
KEY->cleanup(arguments) (in cleanup) |
There is a global variable $main::scope defined in the polymake script. It is initialized with a fresh Poly::Scope object whose lifespan extends over exactly one user cycle, that is, interpreting one complete user input line in the interactive mode or executing the user script in the batch mode. The perform_deferred method is called immediately before the end of the cycle.
Currently this variable is used by all visualization back-ends, as they have to postpone the launch of the visualization program until all requested drawings are gathered. Other important activity is the deletion of the temporary properties created during the cycle.