Exegesis 7
by Damian Conway
|
Pages: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
Editor's note: this document is out of date and remains here for historic interest. See Synopsis 7 for the current design information.
And now at length they overflow their banks.
It's not uncommon for a report to need a series of data fields in one column and then a second column with only single field, perhaps containing a summary or discussion of the other data. For example, we might want to produce recipes of the form:
=================[ Hecate's Broth of Ambition ]=================
Preparation time: Method:
66.6 minutes Remove the legs from the
lizard, the wings from the
Serves: owlet, and the tongue of the
2 doomed souls adder. Set them aside.
Refrigerate the remains (they
Ingredients: can be used to make a lovely
2 snakes (1 fenny, 1 white-meat stock). Drain the
adder) newts' eyes if using pickled.
2 lizards (1 legless, Wrap the toad toes in the
1 regular) bat's wool and immerse in half
3 eyes of newt (fresh a pint of vegan stock in
or pickled) bottom of a preheated
2 toad toes (canned cauldron. (If you can't get a
are fine) fresh vegan for the stock, a
2 cups of bat's wool cup of boiling water poured
1 dog tongue over a vegetarian holding a
1 common or spotted sprouted onion will do). Toss
owlet in the fenny snake, then the
legless lizard. Puree the
tongues together and fold
gradually into the mixture,
stirring widdershins at all
times. Allow to bubble for 45
minutes then decant into two
tarnished copper chalices.
Garnish each with an owlet
wing, and serve immediately.
There are several ways to achieve that effect. The most obvious is to format each column separately and then lay them out side-by-side with a pair of verbatim fields:
my $prep = form 'Preparation time: ',
' {<<<<<<<<<<<<<<<<<<<<}', $prep_time,
' ',
'Serves: ',
' {<<<<<<<<<<<<<<<<<<<<}', $serves,
' ',
'Ingredients: ',
' {[[[[[[[[[[[[[[[[[[[[}', $ingredients;
my $make = form 'Method: ',
' {[[[[[[[[[[[[[[[[[[[[[[[[[[[[}',
$method;
print form
'=================[ {||||||||||||||||||||||||||} ]=================',
$recipe,
' ',
' {"""""""""""""""""""""""} {"""""""""""""""""""""""""""""""} ',
$prep, $make;
We could even chain the calls to form to eliminate the interim variables:
print form
'=================[ {||||||||||||||||||||||||||} ]=================',
$recipe,
' ',
' {"""""""""""""""""""""""} {"""""""""""""""""""""""""""""""} ',
form('Preparation time: ',
' {<<<<<<<<<<<<<<<<<<<<}', $prep_time,
' ',
'Serves: ',
' {<<<<<<<<<<<<<<<<<<<<}', $serves
' ',
'Ingredients: ',
' {[[[[[[[[[[[[[[[[[[[[}', $ingredients,
),
form('Method: ',
' {[[[[[[[[[[[[[[[[[[[[[[[[[[[[}',
$method,
);
While it's impressive to be able to do that kind of nested formatting (and highly useful in extreme formatting scenarios), it's also far too ungainly for regular use. A cleaner, more maintainable solution is use a single format and just build the method column up piecemeal, like so:
print form
'=================[ {||||||||||||||||||||||||||} ]=================',
$recipe,
' ',
'Preparation time: Method: ',
' {<<<<<<<<<<<<<<<<<<<<} {<<<<<<<<<<<<<<<<<<<<<<<<<<<…} ',
$prep_time, $method,
' {…<<<<<<<<<<<<<<<<<<<<<<<<<<…} ',
$method,
'Serves: {…<<<<<<<<<<<<<<<<<<<<<<<<<<…} ',
$method,
' {<<<<<<<<<<<<<<<<<<<<} {…<<<<<<<<<<<<<<<<<<<<<<<<<<…} ',
$serves, $method,
' {…<<<<<<<<<<<<<<<<<<<<<<<<<<…} ',
$method,
'Ingredients: {…<<<<<<<<<<<<<<<<<<<<<<<<<<…} ',
$method,
' {[[[[[[[[[[[[[[[[[[[[} {…[[[[[[[[[[[[[[[[[[[[[[[[[[[} ',
$ingredients, $method;
That produces exactly the same result as the previous versions, because
each follow-on {…<<<<<<<…} field in the
"Method" column grabs one extra line from $method, and then the final
follow-on {…[[[[[[…} field grabs as many more as are required
to lay out the rest of the contents of the variable. The only down-side is
that the resulting code is still downright ugly. With all those tedious
repetitions of the same variable, there's far too much $method
in our madness.
Having a series of follow-on fields like this – vertically
continuing a single column across subsequent format lines – is so
common that form provides a special shortcut: the {VVVVVVVVV}
overflow field.
An overflow field automagically duplicates the field specification immediately above it. The important point being that, because that duplication includes copying the preceding field's data source, overflow fields don't require a separate data source of their own.
Using overflow fields, we could rewrite our quotation generator like this:
print form
'=================[ {||||||||||||||||||||||||||} ]=================',
$recipe,
' ',
'Preparation time: Method: ',
' {<<<<<<<<<<<<<<<<<<<<} {<<<<<<<<<<<<<<<<<<<<<<<<<<<<} ',
$prep_time, $method,
' {VVVVVVVVVVVVVVVVVVVVVVVVVVVV} ',
'Serves: {VVVVVVVVVVVVVVVVVVVVVVVVVVVV} ',
' {<<<<<<<<<<<<<<<<<<<<} {VVVVVVVVVVVVVVVVVVVVVVVVVVVV} ',
$serves,
' {VVVVVVVVVVVVVVVVVVVVVVVVVVVV} ',
'Ingredients: {VVVVVVVVVVVVVVVVVVVVVVVVVVVV} ',
' {[[[[[[[[[[[[[[[[[[[[} {VVVVVVVVVVVVVVVVVVVVVVVVVVVV} ',
$ingredients,
' {VVVVVVVVVVVVVVVVVVVVVVVVVVVV} ';
Which would once again produce the recipe shown earlier.
Note that the overflow fields interact equally well in formats with single-line and block fields. That's because block overflow fields have one other special feature: they're non-greedy. Unless we specify otherwise, all types of block fields will consume their entire data source. For example, if we wrote:
print form :layout«across»,
'{<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>…}',
$speech,
'{…<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>…}',
$speech,
'{…[[[[[]]]]]…} {="""""""""""""""""""=} {…[[[[[]]]]]]…}',
$speech, $advert, $speech,
'{…[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]}',
$speech;
we'd get:
Now is the winter of our discontent / Made glorious summer
by this sun of York; / And all the clouds that lour'd upon
our house / In the deep bosom
of the ocean buried. / Now
are our brows bound with
victorious wreaths; / Our
bruised arms hung up for
monuments; / Our stern
alarums +---------------------+ changed to
merry | | meetings, / Our
dreadful | Eat at Mrs Miggins! | marches to
delightful | | measures. Grim-
visaged war +---------------------+ hath smooth'd
his wrinkled front; / And
now, instead of mounting
barded steeds / To fright the
souls of fearful
adversaries, / He capers
nimbly in a lady's chamber.
That's because the two {…[[[[[]]]]]…} block fields
on either side of the verbatim advertisement field will eat all the
data in $speech, leaving nothing for the final format. Then
the advertisement will be centred on the two resulting columns of text.
But, block overflow fields are different. They only take as many lines as are required to fill the lines generated by the non-overflow fields in their format. So, if we changed our code to use overflows:
print form :layout«across»
'{<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}', $speech,
'{VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV}',
'{VVVVVVVVVVVV} {="""""""""""""""""""=} {VVVVVVVVVVVVV}', $advert,
'{VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV}';
we get both a cleaner specification and a more elegant result:
Now is the winter of our discontent / Made glorious summer
by this sun of York; / And all the clouds that lour'd upon
our house / In the deep bosom
of the ocean +---------------------+ buried. / Now
are our brows | | bound with
victorious | Eat at Mrs Miggins! | wreaths; / Our
bruised arms | | hung up for
monuments; / +---------------------+ Our stern
alarums changed to
merry meetings, / Our dreadful marches to delightful
measures. Grim-visaged war hath smooth'd his wrinkled
front; / And now, instead of mounting barded steeds / To
fright the souls of fearful adversaries, / He capers
nimbly in a lady's chamber.
Notice that, in the third format line of the previous example, the two
overflow fields on either side of the advertisement are each overflowing
from the single field that's above both of them. This kind of multiple
overflow is fine, but it does require that we specify how the various
fields overflow (i.e. as two separate columns of text, or – as in
this case – as a single, broken column across the page). That's
the purpose of the :layout«across» option on the
first line. This option is explained in detail below.
The {VVVVVVVV} fields only consumed as much data from $speech as
was required to sandwich the output lines created by the verbatim
advertisement. This feature is important, because it means we can lay
out a series of block fields in one column and a single overflowed field
in another column without introducing ugly gaps. For example, because
the {VVVVVVVVV} fields in:
print form
"Name: ",
" {[[[[[[[[[[[[} ", $name,
" Biography: ",
"Status: {<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<}", $bio,
" {[[[[[[[[[[[[} {VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV}", $status,
" {VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV}",
"Comments: {VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV}",
" {[[[[[[[[[[[} {VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV}", $comments;
only consume as much of the overflowing $bio field as necessary,
the result is something like:
Name:
William
Shakespeare
Biography:
Status: William Shakespeare was born on
Deceased (1564 April 23, 1564 in Strathford-upon-
-1616) Avon, England; he was third of
eight children from Father John
Comments: Shakespeare and Mother Mary Arden.
Theories Shakespeare began his education at
abound as to the age of seven when he probably
the true attended the Strathford grammar
author of his school. The school provided
plays. The Shakespeare with his formal
prime education. The students chiefly
alternative studied Latin rhetoric, logic, and
candidates literature. His knowledge and
being Sir imagination may have come from his
Francis reading of ancient authors and
Bacon, poetry. In November 1582,
Christopher Shakespeare received a license to
Marlowe, or marry Anne Hathaway. At the time of
Edward de their marriage, Shakespeare was 18
Vere years old and Anne was 26. They had
three children, the oldest Susanna,
and twins- a boy, Hamneth, and a
girl, Judith. Before his death on
April 23 1616, William Shakespeare
had written thirty-seven plays. He
is generally considered the
greatest playwright the world has
ever known and has always been the
world's most popular author.
If {VVVVVVVVVVV} fields ate their entire data – the way
{[[[[[[[[[} or {IIIIIIIIII} fields do – then the output would be
much less satisfactory. The first block overflow field for $bio would
have to consume the entire biography, before the comments field was even
reached. So our output would be something like:
Name:
William
Shakespeare
Biography:
Status: William Shakespeare was born on
Deceased (1564 April 23, 1564 in Strathford-upon-
-1616) Avon, England; he was third of
eight children from Father John
Shakespeare and Mother Mary Arden.
Shakespeare began his education at
the age of seven when he probably
attended the Strathford grammar
school. The school provided
Shakespeare with his formal
education. The students chiefly
studied Latin rhetoric, logic, and
literature. His knowledge and
imagination may have come from his
reading of ancient authors and
poetry. In November 1582,
Shakespeare received a license to
marry Anne Hathaway. At the time of
their marriage, Shakespeare was 18
years old and Anne was 26. They had
three children, the oldest Susanna,
and twins- a boy, Hamneth, and a
girl, Judith. Before his death on
April 23 1616, William Shakespeare
had written thirty-seven plays. He
is generally considered the
greatest playwright the world has
ever known and has always been the
world's most popular author.
Comments:
Theories
abound as to
the true
author of his
plays. The
prime
alternative
candidates
being Sir
Francis
Bacon,
Christopher
Marlowe, or
Edward de
Vere
Which is precisely why {VVVVVVVVVVV} fields don't work that way.

