Saltearse al contenido

5. Paradigma Imperativo

Conceptos clave del paradigma imperativo en OCaml. Punteros (ref) y arrays.

Punteros en OCaml (Ref)

En esencia, con la palabra reservada Ref podemos crear punteros en OCaml. En esencia una referencia, es un puntero que apunta a una celda de referencia, un lugar donde se guardan los cambios que se le aplican al acceder al puntero.

En OCaml un valor (val) es inmutable y eso se mantiene. Los valores no guardan la información, si no solo la referencia al lugar donde esta guardando. Puedes pensarlo como que guardan la dirección de memoria.

ref;;
- : 'a -> 'a ref = <fun>

Podemos declarar un puntero a un tipo entero de la siguiente manera:

let i = ref 0;;
val i : int ref = {contents = 0}

Al contrario que con un int normal no podemos operar con el:

i + 1;;
Line 1, characters 0-1:
1 | i + 1;;
^
Error: The value "i" has type "int ref" but an expression was expected of type
"int"

Si queremos acceder a el podemos usar tanto el asignador := como el conversor !.

!i + 1;;
- : int = 1;;
!i;;
- : int = 0
i := 5;;
- : unit = ()
!i;;
- : int = 5

Factorial en Imperativo

let fac n =
let f = ref 1 and i = ref 1 in
while !i <= n do
f := !f * !i;
i := !i + 1
done;
!f
;;
val fact : int -> int = <fun>

Array

En OCaml debemos diferenciar las listas de los arrays.

  • Esto es una lista:
    [1; 5; 0];;
    - : int list = [1; 5; 0]
  • Esto es un array:
    [|1; 5; 0|];;
    - : int array = [|1; 5; 0|]

Los arrays están ordenados y podemos acceder a cada posición ya sea mediante el método nativo o las funciones del módulo Array:

([|1; 5; 0|]).(1);;
- : int = 5
Array.get ([|1; 5; 0|]) 0;;
- : int = 1

Creación de arrays

  • Creación de un array de 10 elementos con números aleatorios entre 0. y 1.
    let v = Array.init 10 (fun _ -> Random.float 1.);;
    val v : float array =
    [|0.5838873773256934; 0.76749470818256071; 0.55248827110747356;
    0.67603695250431994; 0.16163986467304847; 0.43346122387692643;
    0.14272284143231861; 0.18569275985545408; 0.616357979144595;
    0.13804818153161535|]
  • Creación de un vector resultado del producto vectorial de dos vectores
    let vprod v1 v2 =
    if Array.length v1 = Array.length v2 then
    let p = ref 0. in
    for i = 0 to (Array.length v1) - 1 do
    p := !p +. v1.(i) *. v2.(i)
    done;
    !p
    else
    raise (Invalid_argument "vprod")
    ;;
    val vprod : float array -> float array -> float = <fun>
    vprod [|1.;2.|] [|3.;4.|];;
    - : float = 11.
    • También podemos implementarlo usando funciones del módulo Array
    let vprod v1 v2 =
    Array.fold_left (+.) 0. (Array.map2 ( *. ) v1 v2 )
    ;;
    val vprod : float array -> float array -> float = <fun>
    vprod [|1.;2.|] [|3.;4.|];;
    - : float = 11.
Pablo Portas López © 2025 licensed under CC BY 4.0