Go to the first, previous, next, last section, table of contents.


Quotation

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:

  1. Anti-quoted expression: The sequence $$ marks the beginning and the end of an expression to be evaluated inside the quotation. For instance:
     <<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") $$ >> 
    
  2. Anti-quoted identifier: There is a shorter form when the expression is only a identifier, possibly qualified with a module path and/or a record path:
     <<And the winner is ... $winner !>> 
    
     <<And the winner is ... $Game.winner !>> 
    
  3. Runtime variable: The $$ form is expanded at compile time, so the name of identifiers must be known to the compiler. You can't access directly "run-time" variables, like CGI arguments. Suppose you have a function
    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). >>
     
    
  4. Conditional sections: you can define conditional sections with the notation:
     $?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$?: >>
         
    
  5. Abstraction: Consider the following example:
    
    	<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.
  6. Specials: You have a few metavariables accessible with the notation ${meta} or ${meta:arg}. Here are the possible values for meta:
    1. filename Returns the current file being processed (the ml source file or template file, see later); arg is ignored.
    2. lastmod Computes the last modification date for the current file; if arg is empty or absent, the date is formatted as "yyyy-mm-dd"; otherwise, arg is parsed as a Caml expression yielding a formatting function int -> int -> int -> 'a (whose arguments are in the order year, month, day).
    3. You can of course escape (protect) $$ and $ by a backslash: \$$, \$. The backslash itself can be escaped : \\
    4. A backslash at the end of the line hide the following \n character. All other backslash sequence, such as \n, \t, \013, etc... are disabled. You don't need to escape the quotation mark ".


Go to the first, previous, next, last section, table of contents.