È possibile generalizzare gli aggiornamenti dei campi di registrazione in OCaml?
Domanda
Sono un programmatore OCaml molto alle prime armi quindi per favore perdonami se questa è una domanda stupida / ovvia. C'è molto da assorbire e potrei aver perso questo nella documentazione.
Ho una base di codice che inizia ad apparire così:
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 duplicazione sta iniziando a infastidirmi perché voglio scrivere qualcosa del genere:
let update_scalar p scalar value =
add_delta p;
magic_reflection (p, scalar) <- value;
refresh p
In questo modo quando aggiorno x posso semplicemente chiamare:
update_scalar p 'x' value
Questo richiama " macro! " per me, ma non credo che OCaml abbia un sistema macro. Cos'altro posso fare?
Soluzione
No, non puoi fare quello che vuoi in OCaml. È possibile scrivere un'estensione di sintassi con camlp4 (che è una specie di un sistema macro, sebbene un tipo diverso da quello a cui probabilmente sei abituato) che trasformerebbe
UPDATE_FIELD x f y
in
x.f <- y
In alternativa, puoi inserire le cose in una tabella hash e rinunciare alla sicurezza del tipo.
NOTA: la versione di camlp4 inclusa in OCaml versione 3.10 e successive è diversa e incompatibile con la versione precedente. Per informazioni sull'ultima versione, consultare il sito tutorial OCaml .
Altri suggerimenti
Non puoi fare esattamente quello che vuoi, ma puoi ridurre notevolmente la piastra della caldaia con una funzione di ordine superiore:
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 ha un sistema macro (camlp4) e ti permette di implementare questo tipo di cose, con un po 'di lavoro.
Come notato sopra, ocaml ha un sistema macro. E per questo compito è necessaria solo una piccola parte:
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
Compila con:
ocamlfind ocamlc -package camlp4.macro -syntax camlp4o q.ml -o q
Vedi il codice generato con:
camlp4o Camlp4MacroParser.cmo q.ml