Author: Christian.Queinnec@lip6.fr

## Functional Style

Object-oriented programming usually has an imperative style. A message is sent to an object that physically modifies its internal state (i.e. its data fields). It is also possible to use a functional approach to object-oriented programming: sending a message returns a new object.

#### Object Copy

Objective CAML provides a special syntactic construct for returning a copy of an object `self` with some of the fields modified.

### Syntax

{< name1=expr1;...; namen=exprn >}

This way we can define functional points where methods for relative moves have no side effect, but instead return a new point.

    # class f_point p =
      object
       inherit point p
       method f_rmoveto_x (dx) = {< x = x + dx >}
       method f_rmoveto_y (dy) = {< y = y + dy >}
      end ;;
    class f_point :
      int * int ->
      object ('a)
        val mutable x : int
        val mutable y : int
        method distance : unit -> float
        method f_rmoveto_x : int -> 'a
        method f_rmoveto_y : int -> 'a
        method get_x : int
        method get_y : int
        method moveto : int * int -> unit
        method print : unit -> unit
        method rmoveto : int * int -> unit
        method to_string : unit -> string
      end

With the new methods, movement no longer modifies the receiving object; instead a new object is returned that reflects the movement.

    # let p = new f_point (1,1) ;;
    val p : f_point = <obj>
    # print_string (p#to_string()) ;;
    ( 1, 1)- : unit = ()
    # let q = p#f_rmoveto_x 2 ;;
    val q : f_point = <obj>
    # print_string (p#to_string()) ;;
    ( 1, 1)- : unit = ()
    # print_string (q#to_string()) ;;
    ( 3, 1)- : unit = ()

Since these methods construct an object, it is possible to send a message directly to the result of the method `f_rmoveto_x`.

    # print_string ((p#f_rmoveto_x 3)#to_string()) ;;
    ( 4, 1)- : unit = ()

The result type of the methods `f_rmoveto_x` and `f_rmoveto_y` is the type of the instance of the defined class, as shown by the 'a in the type of `f_rmoveto_x`.

    # class f_colored_point (xc, yc) (c:string) =
       object
         inherit f_point(xc, yc)
         val color = c
         method get_c = color
       end ;;
    class f_colored_point :
      int * int ->
      string ->
      object ('a)
        val color : string
        val mutable x : int
        val mutable y : int
        method distance : unit -> float
        method f_rmoveto_x : int -> 'a
        method f_rmoveto_y : int -> 'a
        method get_c : string
        method get_x : int
        method get_y : int
        method moveto : int * int -> unit
        method print : unit -> unit
        method rmoveto : int * int -> unit
        method to_string : unit -> string
      end

Sending `f_rmoveto_x` to an instance of `f_colored_point` returns a new instance of `f_colored_point`.

    # let fpc = new f_colored_point (2,3) "blue" ;;
    val fpc : f_colored_point = <obj>
    # let fpc2 = fpc#f_rmoveto_x 4 ;;
    val fpc2 : f_colored_point = <obj>
    # fpc2#get_c;;
    - : string = "blue"

One can also obtain a copy of an arbitrary object, using the the primitive `copy` from module `Oo`:

    # Oo.copy ;;
    - : (< .. > as 'a) -> 'a = <fun>
    # let q = Oo.copy p ;;
    val q : f_point = <obj>
    # print_string (p#to_string()) ;;
    ( 1, 1)- : unit = ()
    # print_string (q#to_string()) ;;
    ( 1, 1)- : unit = ()
    # p#moveto(4,5) ;;
    - : unit = ()
    # print_string (p#to_string()) ;;
    ( 4, 5)- : unit = ()
    # print_string (q#to_string()) ;;
    ( 1, 1)- : unit = ()

#### Example: a Class for Lists

A functional method may use the object itself, `self`, to compute the value to be returned. Let us illustrate this point by defining a simple hierarchy of classes for representing lists of integers.
First we define the abstract class, parameterized by the type of list elements.

    # class virtual ['a] o_list () =
     object
       method virtual empty : unit -> bool
       method virtual cons  : 'a -> 'a o_list
       method virtual head :  'a
       method virtual tail : 'a o_list
     end;;

We define the class of non empty lists.

    # class  ['a] o_cons (n ,l)  =
     object (self)
       inherit ['a] o_list ()
       val car = n
       val cdr = l
       method empty () = false
       method cons x = new o_cons (x, (self : 'a #o_list :> 'a o_list))
       method head = car
       method tail = cdr
     end;;
    class ['a] o_cons :
      'a * 'a o_list ->
      object
        val car : 'a
        val cdr : 'a o_list
        method cons : 'a -> 'a o_list
        method empty : unit -> bool
        method head : 'a
        method tail : 'a o_list
      end

We should note that method `cons` returns a new instance of 'a o_cons. To this effect, the type of `self` is constrained to 'a #o_list, then subtyped to 'a o_list. Without subtyping, we would obtain an open type ('a #o_list), which appears in the type of the methods, and is strictly forbidden (see page ??). Without the additional constraint, the type of `self` could not be a subtype of 'a o_list.
This way we obtain the expected type for method `cons`. So now we know the trick and we define the class of empty lists.

    # exception EmptyList ;;
    # class ['a] o_nil () =
      object(self)
       inherit ['a] o_list ()
       method empty () = true
       method cons x = new o_cons (x, (self : 'a #o_list :> 'a o_list))
       method head = raise EmptyList
       method tail = raise EmptyList
      end ;;

First of all we build an instance of the empty list, and then a list of integers.

    # let i = new o_nil ();;
    val i : '_a o_nil = <obj>
    # let l = new o_cons (3,i);;
    val l : int o_list = <obj>
    # l#head;;
    - : int = 3
    # l#tail#empty();;
    - : bool = true

The last expression sends the message tail to the list containing the integer 3, which triggers the method `tail` from the class 'a o_cons. The message empty(), which returns `true`, is sent to this result. You can see that the method which has been executed is `empty` from the class 'a o_nil.