Before we describe the new syntax, we have to introduce a tiny module : Text (what an original name). With this module, every Caml value "is" a string. To understand what it means, let's define the "string content" S(x) of a value x. It is a string, defined by:
Similarly, the "string components" SC(x) is defined by:
The module defines an opaque type
an "universal constructor"
Text.repr: 'a -> t.
Text.iter:(string -> unit) -> t -> unit
applies a given function to the string components of a
There are also two functions to compute S(x) and its length.
So, for instance, we have (oh yes, this is not well-typed; you have
S("Hello world !") = "Hello world !"
S(["Hello";(" ","World");Some " !"]) = "Hello world !"
S([|"Hello"; 5; Some (5," "); "World !"|]) = "Hello world !"
Typically, an application builds its output by concatenating strings.
This involves many copy operations so it may be quite slow.
With the module Text, just put your substrings in a list (or better,
an array: only one big block), and see it as a string with
Text.repr. When you want to finally output the "string", use
Text.to_string on the result.
Another feature of the module Text is the manipulation of "postponed texts". Suppose you want to create a text with a hole to be filled later, when an extra piece of information is available. A simple way to use a reference:
let post = ref Text.empty in repr [Text.repr "Total size :"; Text.repr post]; (* ... *) post := Text.repr (string_of_int (total_size ()));
Sometimes it is better to put the expression to be computed later at the position of the postponed text, then to activate it later; also, having a global reference is not easy to manage. You can do that:
repr [Text.repr "Total size :"; Text.postponed "totalsize" (fun () -> Text.repr (string_of_int (total_size ())))]; (* ... *) Text.activate "totalsize"
Here, "totalsize" identifies the delayed computation and Text.activate triggers the evaluation.
Go to the first, previous, next, last section, table of contents.