Author: Christian.Queinnec@lip6.fr

## Other Libraries in the Distribution

The other libraries provided with the Objective CAML language distribution relate to the following extensions:

- graphics, with the portable `Graphics` module that was described in chapter 5;
- exact math, containing many modules, and allowing the use of exact calculations on integers and rational numbers. Numbers are represented using Objective CAML integers whenever possible;
- regular expression filtering, allowing easier string and text manipulations. The `Str` module will be described in chapter 11;
- Unix system calls, with the `Unix` module allowing one to make unix system calls from Objective CAML. A large part of this library is nevertheless compatible with Windows. This bibliography will be used in chapters 18 and 20;
- light-weight processes, comprising many modules that will largely be described and used in chapter 19;
- access to NDBD databases, works only in Unix and will not be described;
- dynamic loading of bytecode, implemented by the `Dynlink` module.

We will describe the big integer and dynamic loading libraries by using them.

### Exact Math

The big numbers library provides exact math functions using integers and rational numbers. Values of type int and float have two limitations: calculations on integers are done modulo the greatest positive integer, which can cause unperceived overflow errors; the results of floating point calculations are rounded, which by propagation can lead to errors. The library presented here mitigates these defects.
This library is written partly in C. For this reason, you have to build an interactive loop that includes this code using the command:

    ocamlmktop -custom -o top nums.cma -cclib -lnums

The library contains many modules. The two most important ones are `Num` for all the operations and `Arith_status` for controlling calculation options. The general type num is a variant type gathering three basic types:

    type num = Int of int
             | Big_int of big_int
             | Ratio of ratio

The types big_int and ratio are abstract.
The operations on values of type num are followed by the symbol `/`. For example the addition of two num variables is written `+/` and will be of type num -> num -> num. It will be the same for comparisons. Here is the first example that calculates the factorial:

    # let rec fact_num n =
       if  Num.(<=/) n  (Num.Int 0) then (Num.Int 1)
       else  Num.( */ ) n  (fact_num ( Num.(-/) n (Num.Int 1)));;
    val fact_num : Num.num -> Num.num = <fun>
    # let r = fact_num (Num.Int 100);;
    val r : Num.num = Num.Big_int <abstr>
    # let n = Num.string_of_num r in (String.sub n 0 50) ^ "..." ;;
    - : string = "93326215443944152681699238856266700490715968264381..."

Opening the `Num` module makes the code of `fact_num` easier to read:

    # open Num ;;
    # let rec fact_num n =
       if  n <=/  (Int 0) then (Int 1)
       else  n */   (fact_num ( n -/ (Int 1))) ;;
    val fact_num : Num.num -> Num.num = <fun>

Calculations using rational numbers are also exact. If we want to calculate the number e by following the following definition:

e = lim |
m -> ¥
|  | æ ç ç è | 1 + |
1
m
|  | ö ÷ ÷ ø |
m

We should write a function that calculates this limit up to a certain m.

    # let  calc_e m =
       let a = Num.(+/) (Num.Int 1) ( Num.(//) (Num.Int 1) m) in
         Num.( **/ ) a  m;;
    val calc_e : Num.num -> Num.num = <fun>
    # let r = calc_e (Num.Int 100);;
    val r : Num.num = Ratio <abstr>
    # let n = Num.string_of_num r in (String.sub n 0 50) ^ "..." ;;
    - : string = "27048138294215260932671947108075308336779383827810..."

The `Arith_status` module allows us to control some calculations such as the normalization of rational numbers, approximation for printing, and processing null denominators. The `arith_status` function prints the state of these indicators.

    # Arith_status.arith_status();;

    Normalization during computation --> OFF
         (returned by get_normalize_ratio ())
         (modifiable with set_normalize_ratio <your choice>)

    Normalization when printing --> ON
         (returned by get_normalize_ratio_when_printing ())
         (modifiable with set_normalize_ratio_when_printing <your choice>)

    Floating point approximation when printing rational numbers --> OFF
         (returned by get_approx_printing ())
         (modifiable with set_approx_printing <your choice>)

    Error when a rational denominator is null --> ON
         (returned by get_error_when_null_denominator ())
         (modifiable with set_error_when_null_denominator <your choice>)
    - : unit = ()

They can be modified according to the needs of a calculation. For example, if we want to print an approximate value for a rational number, we can obtain, for the preceding calculation:

    # Arith_status.set_approx_printing true;;
    - : unit = ()
    # Num.string_of_num (calc_e (Num.Int 100));;
    - : string = "0.270481382942e1"

Calculations with big numbers take longer than those with integers and the values occupy more memory. Nevertheless, this library tries to use the most economical representations whenever possible. In any event, the ability to avoid the propagation of rounding errors and to do calculations on big numbers justifies the loss of efficiency.

### Dynamic Loading of Code

The `Dynlink` module offers the ability to dynamically load programs in the form of bytecode. The dynamic loading of code provides the following advantages:

- reduces the size of a program's code. If certain modules are not used, they are not loaded.
- allows the choice at execution time of which module to load. According to certain conditions at execution time you choose to load one module rather than another.
- allows the modification of the behavior of a module during execution. Here again, under some conditions the program can load a new module and hide the old code.

The interactive loop of Objective CAML already uses such a mechanism. It is convenient to let the programmer have access to it as well.
During the loading of an object file (with the `.cmo` extension), the various expressions are evaluated. The main program, that initiated the dynamic loading of the code does not have access to the names of declarations. Therefore it is up to the dynamically loaded module to update a table of functions used by the main program.

### Warning

The dynamic loading of code only works for object files in bytecode.

#### Description of the Module

For dynamic loading of a bytecode file `f.cmo`, we need to know the access path to the file and the names of the modules that it uses. By default, dynamically loaded bytecode files do not have access to the paths and modules of the libraries in the distribution. Thus we have to add the path and the name of the required modules to the dynamic loading of the module.

> `init` | : | unit -> unit
> |  | initialize dynamic loading
> `add_interfaces` | : | string list -> string list -> unit
> |  | add the names of modules and paths for loading
> `loadfile` | : | string -> unit
> |  | load a bytecode file
> `clear_avalaible_units` | : | unit -> unit
> |  | empty the names of loadable modules and paths
> `add_avalaible_units` | : | (string * Digest.t) list -> unit
> |  | add the name of a module and a checksum for loading without needing the interface file
> `allow_unsafe_modules` | : | bool -> unit
> |  | allow the loading of files containing external declarations
> `loadfile_private` | : | string -> unit
> |  | the loaded module is not accessible to modules loaded later
> The checksum of an interface `.cmi` can be obtained from the `extract_crc` command found in the catalog of libraries in the distribution.

> Figure 8.10: Functions of the `Dynlink` module.

Many errors can occur during a request to load a module. Not only must the file exist with the right interface in one of the paths, but the bytecode must also be correct and loadable. These errors are gathered in the type error used as an argument to the `Error` exception and to the `error` function of type error -> string that allows the conversion of an error into a clear description.

#### Example

To write a small program that allows us to illustrate dynamic loading of bytecode, we provide three modules:

- `F` that contains the definition of a reference to a function `f`;
- `Mod1` and `Mod2` that modify in different ways the function referenced by `F.f`.

The `F` module is defined in the file `f.ml`:

    let g () =
      print_string "I am the 'f' function by default\n" ; flush stdout  ;;
    let f = ref g ;;

The `Mod1` module is defined in the file `mod1.ml`:

    print_string "The 'Mod1' module modifies the value of 'F.f'\n" ; flush stdout ;;
    let g () =
      print_string "I am the 'f' function of module 'Mod1'\n" ;
      flush stdout ;;
    F.f := g ;;

The `Mod2` module is defined in the file `mod2.ml`:

    print_string "The 'Mod2' module modifies the value of 'F.f'\n" ; flush stdout ;;
    let g () =
      print_string "I am the 'f' function of module 'Mod2'\n" ;
      flush stdout ;;
    F.f := g ;;

Finally we define in the file `main.ml`, a main program that calls the original function referenced by `F.f`, loads the `Mod1` module, calls `F.f` again, then loads the `Mod2` module and calls the `F.f` function one last time:

    let main () =
      try
        Dynlink.init () ;
        Dynlink.add_interfaces [ "Pervasives"; "F" ; "Mod1" ; "Mod2" ]
                               [ Sys.getcwd() ; "/usr/local/lib/ocaml/" ] ;
        !(F.f) () ;
        Dynlink.loadfile "mod1.cmo" ;  !(F.f) () ;
        Dynlink.loadfile "mod2.cmo" ;  !(F.f) ()
      with
        Dynlink.Error e -> print_endline (Dynlink.error_message e) ; exit 1 ;;

    main () ;;

The main program must, in addition to initializing the dynamic loading, declare by a call to `Dynlink.add_interfaces` the interface used.
We compile all of these modules:

    $ ocamlc -c f.ml
    $ ocamlc -o main dynlink.cma f.cmo main.ml
    $ ocamlc -c f.cmo mod1.ml
    $ ocamlc -c f.cmo mod2.ml

If we execute program `main`, we obtain:

    $ main
    I am the 'f' function by default
    The 'Mod1' module modifies the value of 'F.f'
    I am the 'f' function of module 'Mod1'
    The 'Mod2' module modifies the value of 'F.f'
    I am the 'f' function of module 'Mod2'

Upon the dynamic loading of a module, its code is executed. This is demonstrated in our example, with the outputs beginning with `The 'Mod...`. The possible side effects that it contains are therefore reflected at the level of the program that caused the code to be loaded. This is why the different calls to `F.f` call different functions.
The `Dynlink` library offers the basic mechanism for dynamically loading bytecode. The programmer still has to manage tables such that the loading will really be effective.