declaration/definition
define string sink function function-name function-argument-list (as function-body | elsewhere) or define external string sink function function-name function-argument-list as external name (in function-library library-name)?
Defines a function that serves as a sink (or destination) of
string
s. This replaces define external output function
from previous
versions of OmniMark; that form is now deprecated. It also extends
the functionality to internal functions.
A string sink
function is like an ordinary action function, in that it
does not return
a value to its calling context. Instead, it reads
strings
output from the scope it is invoked from.
A return
action without a value can be used to end a string sink
function; alternatively, the function can be allowed to fall off its
end.
There is only one restriction on what can be done in the body of an
internal string sink
function: #current-output
is not attached at the
beginning of the function. Most other operations are available.
Unlike an ordinary function, a string sink
function executes
concurrently with its caller: its input streamed incrementally from its calling context,
without being buffered.
A string sink
function is invoked by calling it in a context that
expects a destination for string
s. Additionally, an internal string sink
function can only be invoked in a well-scoped context. A
well-scoped context as the destination of a using output as
scope, the destination of a put
action, or a value string sink
argument to another function. An
externally-defined string sink
function can be invoked in any context
that expects a destination for string
s: as the argument of output-to
,
as the attachment on an open
action, on the left-hand side of the set
action, and so on. For example, a string sink
function
called uppercase
, can be invoked as follows:
define string sink function uppercase (value string sink s) elsewhere process local stream s open s as buffer using output as uppercase (s) output "Hello, World!%n" close s output s
A filter can be written using a string sink
function that takes an
argument of type value string sink
. The string sink
function scans its
#current-input
, performs any filtering operations necessary, and
outputs the filtered data to its string sink
argument.
For example, the string sink
function uppercase
mentioned above might
be implemented as
define string sink function uppercase (value string sink s) as using output as s repeat scan #current-input match letter+ => t output "ug" % t match [any \ letter]+ => t output t again
uppercase
filters its #current-input
using a repeat scan
loop,
generating an uppercased version of the same string. It outputs
this string to its value string sink
argument s.
A longer example: filtering markup output
A string sink
function provides a simple way of filtering the output
of markup processing. The following process
rule parses some SGML
input, and outputs the result of its processing to a file:
process using output as file "output.txt" do sgml-parse document scan file "input.sgml" output "%c" done element #implied output "%c"
If we wanted to uppercase the output from the markup parse, we could
capture the data in a buffer, perform some post-processing, and output
the data to the destination file. However, this buffers the entire
document output from the markup parse, which is potentially
prohibitively expensive. Alternately, we could wrap the invocation of
the SGML parser in a string source
function:
define string source function wrapper (value string filename) as do sgml-parse document scan file filename output "%c" done process using output as file "output.txt" repeat scan wrapper ("input.sgml") match letter+ => t output "ug" % t match [any \ letter]+ => t output t again
However, a less invasive solution is to use the uppercase
function
described earlier, and to write the process
rule as
process using output as uppercase (file "output.txt") do sgml-parse document scan file "input.sgml" output "%c" done
This solution has minimal impact on the existing code, and all data is streamed from one process to another.