Les mises à jour de champs d'enregistrement dans OCaml peuvent-elles être généralisées?

StackOverflow https://stackoverflow.com/questions/215770

  •  03-07-2019
  •  | 
  •  

Question

Je suis un programmeur OCaml très novice, alors veuillez me pardonner s’il s’agit d’une question stupide / évidente. Il y a beaucoup à absorber et j'ai peut-être manqué cela dans la documentation.

J'ai une base de code qui commence à ressembler à ceci:

let update_x p x =
  add_delta p;
  p.x <- x;
  refresh p

let update_y p y =
  add_delta p;
  p.y <- y;
  refresh p

let update_z p z =
  add_delta p;
  p.z <- z;
  refresh p 

La duplication commence à me causer des ennuis parce que je veux écrire quelque chose comme ceci:

let update_scalar p scalar value =
    add_delta p;
    magic_reflection (p, scalar) <- value;
    refresh p

Ainsi, lorsque je mets à jour x, je peux simplement appeler:

update_scalar p 'x' value

Ceci appelle "macros!" pour moi, mais je ne crois pas que OCaml a un système macro. Que puis-je faire d'autre?

Était-ce utile?

La solution

Non, vous ne pouvez pas faire ce que vous voulez en clair OCaml. Vous pouvez écrire une extension de syntaxe avec camlp4 (qui est une sorte de un système macro, bien que différent de celui auquel vous êtes probablement habitué) qui transformerait

UPDATE_FIELD x f y

dans

x.f <- y

Vous pouvez également insérer des éléments dans une table de hachage sans renoncer à la sécurité.

REMARQUE: La version de camlp4 incluse dans les versions 3.10 et ultérieures d'OCaml est différente et incompatible avec la version précédente. Pour plus d'informations sur la dernière version, voir le site du didacticiel OCaml .

Autres conseils

Vous ne pouvez pas faire ce que vous voulez, mais vous pouvez réduire considérablement le passe-passe avec une fonction d'ordre supérieur:

let update_gen set p x =
  add_delta p;
  set p x;
  refresh p

let update_x = update_gen (fun p v -> p.x <- v)
let update_y = update_gen (fun p v -> p.y <- v)
let update_z = update_gen (fun p v -> p.z <- v)

OCaml a un système de macros (camlp4) qui vous permet d’implémenter ce genre de choses, avec quelques travaux.

Comme indiqué ci-dessus, ocaml a un système macro. Et pour cette tâche, seule une petite fraction est nécessaire:

open Printf

type t = { mutable x : float; mutable y : float; mutable z : float; mutable t : int; }

let add_delta p = p.t <- p.t + 1
let refresh p = printf "%d) %.2f %.2f %.2f\n" p.t p.x p.y p.z

DEFINE UPD(x) = fun p v ->
  add_delta p;
  p.x <- v;
  refresh p

let update_x = UPD(x)
let update_y = UPD(y)
let update_z = UPD(z)

let () =
  let p = { x = 0.; y = 0.; z = 0.; t = 0; } in
  update_x p 0.1;
  update_y p 0.3;
  update_z p 2.0

Compiler avec:

ocamlfind ocamlc -package camlp4.macro -syntax camlp4o q.ml -o q

Voir le code généré avec:

camlp4o Camlp4MacroParser.cmo q.ml
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top