Loading ...
Sorry, an error occurred while loading the content.

2741Re: "ocaml_beginners"::[] Re: 'ocaml_beginners'::[] Re: 'ocaml_beginners'::[] Execution semantics

Expand Messages
  • Martin Jambon
    Nov 4, 2004
    • 0 Attachment
      On Thu, 4 Nov 2004, andrew cooke wrote:

      > That seems easy to do with a reference, but how does it shed light on the
      > relative optimisations for examples 1 and 2? Are you saying that the
      > optimisations used depend on whether there are mutable values (which I'm
      > sure is true)?
      > Or that OCaml only does optimisations that are safe in the
      > presence of mutable values (which seems pretty limiting for a functional
      > language)?

      Yes. OCaml is not a pure functional language. It is possible to make a
      program compute things in a specified order without difficulties.
      And the compiler generally doesn't know which functions perform side
      effects.
      You can write:
      for i = 1 to 100_000_000 do
      ignore (1 + 1)
      done

      This will perform 100 million times the same addition.

      These examples have a different semantics:

      >> let example1 a b x =
      >> let a' = f1 a in
      >> let b' = f2 b in
      >> f3 a' b' x

      example1 a b just creates an object that is a function that will accept
      one argument (x) and compute everything after the equal
      sign (=)

      example1 a b x computes everything after the equal sign

      >> let example2 a b =
      >> let a' = f1 a in
      >> let b' = f2 b in
      >> fun x -> f3 a' b' x

      example2 a b computes everything after the equal sign:
      - f1 a
      - f2 b
      - builds the function which is returned as a result

      example2 a b x is strictly equivalent to
      (example2 a b) x which computes the following:
      - f1 a
      - f2 b
      - applies (fun x -> f3 a' b') to x which may not
      involve the creation of a specific object
      representing the temporary function because it is
      applied immediately (that's a possible optimisation)

      Note that example1 can be rewritten as:

      let example1' a b =
      fun x ->
      let a' = f1 a in
      let b' = f2 b in
      f3 a' b' x

      example1' a b like before, computes everything after the equal sign,
      which only consists in building a function that may even
      not exist as a physical object (e.g. if it is applied
      immediately).

      The following is the example of the counter. It is essential to be sure
      when a new counter is created and when not:

      [droopy] ~ % ledit ocaml
      Objective Caml version 3.08.1

      # let make_counter init =
      let counter = ref init in
      ((fun () -> !counter), (fun () -> incr counter));;
      val make_counter : int -> (unit -> int) * (unit -> unit) = <fun>
      # let (get1, step1) = make_counter 1;;
      val get1 : unit -> int = <fun>
      val step1 : unit -> unit = <fun>
      # let (get2, step2) = make_counter 1;;
      val get2 : unit -> int = <fun>
      val step2 : unit -> unit = <fun>
      # get1 ();;
      - : int = 1
      # get2 ();;
      - : int = 1
      # step1 ();;
      - : unit = ()
      # get1 ();;
      - : int = 2
      # get2 ();;
      - : int = 1


      In practice, this kind of things can be useful if a datastructure has to
      be initialized, e.g.:

      let is_in l =
      let tbl = Hashtbl.create (List.length l) in
      List.iter (fun aa -> Hashtbl.add tbl aa ()) l;
      Hashtbl.mem tbl

      let is_in_abc = is_in ['a'; 'b'; 'c']
      let is_in_123 = is_in [1; 2; 3; 12; 23; 31; 123; 231; 312]


      Martin
    • Show all 26 messages in this topic