![]() |
|
||||
![]() ![]() ![]() ![]() ![]() ![]() ![]() |
|||||
|
|
|||||
| Prerequisite Concepts | Related Topics | ||||
Output scopes |
|||||
OmniMark distinguishes the act of creating output from the act of selecting the output destination, meaning that
the stream that receives the output data does not have to be lexically in scope for you
to output to it. Instead, a stream or a string sink can be placed in an output execution
scope. While a stream is in the current output scope, all output statements will output to it
regardless of the lexical scope they occur in.
You can use the keywords using output as to create an output scope and to place a stream variable
into that output scope. Like any other kind of scope, output scopes can be nested:
process
local stream foo
open foo as file "foo.txt"
using output as foo
do
output "<rhyme>"
submit "Mary had a little lamb"
output "</rhyme>"
done
find ("Mary" | "lamb") => person
local stream foo
reopen foo as file "foo2.txt"
using output as foo
output "<person>" || person || "</person>"
Here a new output scope is established in the find rule, causing the material output in the find rule to be sent to a different destination. This output scope is nested inside the output scope created in the process rule. This scope becomes the current output scope again as soon as the find rule exits.
You can also place a stream into the current output scope, without creating a new output scope, using
output-to:
global stream foo
global stream bar
process
open foo as buffer
open bar as buffer
using output as foo
submit "Mary had a little lamb"
close foo
close bar
output "Foo contains: " || foo
output "%nBar contains: " || bar
find " a "
output-to bar
This program outputs the following:
Foo contains: Mary had Bar contains: little lamb
The output-to in the find rule resets the destination of the output scope established by the using output
as in the process rule. Thus the rest of the text goes to the new destination.
In general, you should use using output as rather then output-to, but
output-to is useful in certain situations, especially when the destination of data is determined by
examining the data itself.
Consider a piece of XML that might be used to send files across a network. It encapsulates the name of the file
and its contents inside "name" and encapsulates "data" elements inside a "file" element:
<file> <name>myfile.txt</name> <data>The content of the file.</data> </file>
We can process this with the following program:
global stream file-data
process
do xml-parse document
scan file "files.xml"
suppress
done
element file
suppress
close file-data
element name
open file-data as file "%c"
output-to file-data
element data
output "%c"
Here the entire processing of the XML is done in a single output scope, but every time we find a filename in the
input we change the destination of the current output scope. It would be difficult to do the same thing with
using output as, because the "data" element is not nested inside the "filename" element, so an output
scope established in the "name" element would have expired before the "data" element was processed.
(By the way, the example shows poor XML language design. It would have been better to make the filename an attribute of the "file" element. But you can't always control the format of the data you have to process.)
If you use output-to, note that placing a stream into an output scope does not exempt it from the
rules of lexical scoping when it comes to the life span of variables. Local variables are created when their
lexical scope enters execution scope and destroyed when their lexical scope leaves execution scope. It is an error
to allow a local variable to go out of execution scope while it is still in an output scope. You will avoid this
problem if you stick to using using output as to create output scopes.
|
Prerequisite Concepts
|
Related Topics
|
Copyright © Stilo International plc, 1988-2010.