Scope::Escape::Sugar - whizzy syntax for non-local control transfer
use Scope::Escape::Sugar qw(with_escape_function with_escape_continuation); { with_escape_function $e; ...; $e->($r); ...; } with_escape_function $e { ...; $e->($r); ...; } $res = with_escape_function($e { ...; $e->($r); ...; }); { with_escape_continuation $e; ...; $e->($r); ...; } with_escape_continuation $e { ...; $e->($r); ...; } $res = with_escape_continuation($e { ...; $e->($r); ...; }); use Scope::Escape::Sugar qw(block return_from); { block foo; ...; return_from foo $r; ...; } block foo { ...; return_from foo $r; ...; } $res = block(foo { ...; return_from foo $r; ...; }); use Scope::Escape::Sugar qw(catch throw); { catch "foo"; ...; } catch "foo" { ...; } $res = catch("foo" { ...; }); throw("foo", $r);
This module provides specialised syntax for non-local control transfer (jumping between stack frames), mainly based on the operators in Common Lisp. The non-local control transfers behave exactly like those of Scope::Escape, which should be consulted for the semantic details. This module provides more structured facilities, which take a variety of approaches to referencing the stack frame to be transferred to.
All the keywords and functions exported by this module are lexically scoped in the importing code. That is, they are available from the point of importation up to the end of the enclosing block. This is in contrast to the more common arrangement where exports are tied to a package without regard for lexical boundaries.
The items shown here are mostly not ordinary functions. Most are keywords that introduce a form that has some special syntax, not conforming to the ordinary Perl syntax. The documentation shows the complete syntax of the forms headed by the keyword. The complete form may be either a statement or an expression, as indicated in the documentation. The keyword is only recognised if it appears as a bareword at the start of a statement/expression.
This facility provides direct access to the continuation functions/objects implemented by Scope::Escape, referenced through lexically-scoped variables. It is just slightly more structured than direct use of Scope::Escape's operators.
In each version, there is a code block and a variable ESCAPE_VAR. ESCAPE_VAR is a lexically-scoped (my-like) scalar variable. Its name must start with a $ sigil, and must not include package qualification. ESCAPE_VAR will be defined lexically, being visible in the code textually contained within the block. Its value will be a reference to an escape continuation targetting the block. Calling the continuation as a function will result in the code block exiting, returning the values that were passed to the continuation.
my
$
Do not assign a new value to ESCAPE_VAR. In this version of this module, ESCAPE_VAR behaves like a normal writable variable, but this is an implementation accident and may change in a future version.
This form is a complete statement, ending with semicolon. ESCAPE_VAR is lexically defined within the enclosing block (from this statement to the end of the block), and contains a reference to an unblessed escape function for the enclosing block.
This form is a complete statement, ending with the closing brace of BLOCK. BLOCK is executed normally. ESCAPE_VAR is lexically defined within BLOCK, and contains a reference to an unblessed escape function for the BLOCK.
This form is an expression. BLOCK is executed normally, and its return value will become the value of this expression. ESCAPE_VAR is lexically defined within BLOCK, and contains a reference to an unblessed escape function for the BLOCK.
This form is a complete statement, ending with semicolon. ESCAPE_VAR is lexically defined within the enclosing block (from this statement to the end of the block), and contains a reference to a blessed escape continuation for the enclosing block.
This form is a complete statement, ending with the closing brace of BLOCK. BLOCK is executed normally. ESCAPE_VAR is lexically defined within BLOCK, and contains a reference to a blessed escape continuation for the BLOCK.
This form is an expression. BLOCK is executed normally, and its return value will become the value of this expression. ESCAPE_VAR is lexically defined within BLOCK, and contains a reference to a blessed escape continuation for the BLOCK.
This facility provides lexical scoping of names for non-locally returnable blocks, while avoiding visible reification of continuations. (with_escape_function and with_escape_continuation provide the same lexical scoping, but reify the continuations and put the lexical names in the ordinary scalar variable namespace.)
with_escape_function
with_escape_continuation
In each version, there is a code block which is labelled with a static bareword identifier TAG. The tag is lexically scoped, being visible in the code textually contained within the block. The return_from keyword can then be used to return from the textually enclosing block with a specified tag.
return_from
In Common Lisp (the model for these special forms), there are many implicit returnable blocks, in addition to the explicit ones established by the block operator. Most notably, the body of each defun-defined function is a returnable block tagged with the function's name. This module does not perceive any such implicit blocks: a return_from form will only return from a block explicitly established with block.
block
defun
This form is a complete statement, ending with semicolon. The enclosing block (from this statement to the end of the block) is returnable, tagged with TAG.
This form is a complete statement, ending with the closing brace of BLOCK. BLOCK is executed normally. BLOCK is returnable, tagged with TAG.
This form is an expression. BLOCK is executed normally, and its return value will become the value of this expression. BLOCK is returnable, tagged with TAG.
This form is an expression. It transfers control to exit from the lexically enclosing returnable block tagged with TAG. If there is no matching block, it is a compile-time error. Zero or more VALUEs may be supplied, which will be returned from the block. (Each VALUE is stated as an expression, which is evaluated normally.)
Due to limitations of the API available to add-on parsing code, the form without parentheses is only available when it is the first thing in a statement.
This facility provides dynamic scoping of names for non-locally returnable blocks, while avoiding visible reification of continuations. The blocks can "catch" values that are "thrown" by lexically-remote code. (There is some resemblance here to throwing and catching of exceptions, but this is not an exception mechanism in itself.)
In each version, there is a code block which is labelled with a (possibly runtime-generated) string identifier TAG. In the catch form, TAG must be stated as a double-quoted or single-quoted string syntax, possibly including variable interpolation. The tag is dynamically scoped, being visible during the execution of the block. The throw function can then be used to return from (throw a value to) the dynamically enclosing block (the catch block) with a specified tag.
catch
throw
The Common Lisp catch and throw operators allow any object to be used as a catch tag, and the tags are compared for object identity. This allows code to generate a catch tag that is guaranteed to be unique, simply by using a newly-allocated cons cell or similar object that is not referenced from anywhere else. If that sort of semantic is required, it is best implemented by using the with_escape_function operator and saving the continuation reference in a localised global variable. It is more usual for Common Lisp catch tags to be symbols, which idiomatically correspond to Perl strings, compared for string equality.
local
This form is a complete statement, ending with semicolon. The enclosing block (from this statement to the end of the block) is a catch block, tagged with TAG.
This form is a complete statement, ending with the closing brace of BLOCK. BLOCK is executed normally. BLOCK is a catch block, tagged with TAG.
This form is an expression. BLOCK is executed normally, and its return value will become the value of this expression. BLOCK is a catch block, tagged with TAG.
This is a function; all arguments are evaluated normally. It transfers control to exit from the dynamically enclosing catch block tagged with TAG. If there is no matching block, it is a runtime error. (Currently signalled by die, but this may change in the future.) Zero or more VALUEs may be supplied, which will be returned from the catch block.
die
The constructs that declare lexically-scoped variables do not generate the "masks earlier declaration" warnings that they should.
Due to limitations of the API available to add-on parsing code, some of the keywords are implemented by rewriting the source for the normal Perl parser to parse. This process risks unwanted interaction with other syntax-mutating modules. The resulting failures are likely to be rather mystifying.
The lexical variable defined by with_escape_function and with_escape_continuation is writable. It really ought to be read-only.
Due to the aforementioned limitations of the API available to add-on parsing code, the version of return_from without parentheses is only available when it is the first thing in a statement. Since a return_from expression never returns locally, there is little reason for it to be a subexpression anyway.
Scope::Escape
Andrew Main (Zefram) <zefram@fysh.org>
Copyright (C) 2010 Andrew Main (Zefram) <zefram@fysh.org>
This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
To install Scope::Escape::Sugar, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Scope::Escape::Sugar
CPAN shell
perl -MCPAN -e shell install Scope::Escape::Sugar
For more information on module installation, please visit the detailed CPAN module installation guide.