È possibile generalizzare gli aggiornamenti dei campi di registrazione in OCaml?

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

  •  03-07-2019
  •  | 
  •  

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?

È stato utile?

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top