HereDoc defines the quotation <:here<...>>. It returns
a value of type Text.t (see See section The module Text: Convenient text manipulation.)).
HereDoc declare this quotation as the
default quotation, so you can simply write <<...>>.
The quotation content is interpreted with the following rules:
<<The winner is $$[|"John";"Bob"|].(win)$$. >>You can use any identifier in the scope at the quotation position. The expression can return a value of any type, and it will be interpreted with the module Text (with
Text.repr).
For instance, it can return a list
of strings, and it will be interpreted as you would expect:
<<The winners are : $$List.map String.uppercase ["John";"Bob"]$$>>Note that inside the expression, you can use another quotation (yet another stupid example):
<< Tada $$ (<<Hello>>, " World") $$ >>
<<And the winner is ... $winner !>>
<<And the winner is ... $Game.winner !>>
val var : string -> 'a = <fun>which can expand these run-time variables (for instance, it can lookup in the table of CGI arguments) where, as usual, the result is to be interpreted through the module Text. You can write:
<< $$var "street"$$>>You have a short form for this:
<< $(street)>>The name of the expanding function is "var" by default; but you can change this with the toplevel directive:
VAR_HANDLER "myfun"It is important to understand that the name of the expanding function is static, but the real function depends on the scope of the quotation. Here's the traditionnaly stupid example:
let var = function
| "birthday" -> "May 13th"
| "firstname -> "Alain"
in
<< This year, $(firstname)'s birthday is on $(birthday). >>
$?expr:where
expr is a boolean expression. If the expression
evaluates to true (during runtime), the text between this
conditional and the next one (or the end of the quotation) is
included. Otherwise, it is discarded.
The empty conditional $?: is equivalent to
$?true:.
Here is an example:
let (fr,en) = (true,false) in
let name = "John" in
<< $?fr:Bonjour$?en:Hello$?: $name >>
You can use more complex expressions:
<< $?Random.int 10 = 0 :lucky man$?: >>
<ul> $$List.map (fun x -> << <li>$x</li> >>) l$$ </ul>HereDoc provides a nicer notation for this kind of iteration:
$[e -> p1 -> p2 ... -> pn]$
....
$[]$
is equivalent to:
$$e (fun p1 ... pn -> <<....>>)$$
e is an expression which evaluates to a function with
n curryfied arguments. p1, ..., pn are patterns.
The last .... is called the abstracted text.
For instance, suppose you have defined:
let map l f= List.map f l
let rec mapi n l f =
match l with
| [] -> []
| t::q -> (f n t)::(mapi (n+1) q f)
You can write this html table renderer:
<table>
$[mapi 1 t -> i -> ligne]$
<tr>
<td><b>$$string_of_int i$$:</b></td>
$[map ligne -> case]$
<td>$case</td>
$[]$
</tr>
$[]$
</table>
The case n=0 is useful to filter the text through a
function. For instance, if box: Text.t -> Text.t is
a function which put a frame around its argument, you can write:
$[box]$ Long long text ... $[]$
Note:
Conditional sections are local to the abstracted text.
${meta} or ${meta:arg}.
Here are the possible values for meta:
int -> int -> int -> 'a (whose arguments are in the order
year, month, day).
Go to the first, previous, next, last section, table of contents.