Macros OCaml中的记录字段更新是否可以通用化?

Macros OCaml中的记录字段更新是否可以通用化?,macros,ocaml,records,Macros,Ocaml,Records,我是一个非常新手的OCaml程序员,所以如果这是一个愚蠢/明显的问题,请原谅我。有很多东西需要吸收,我可能在文档中遗漏了这一点 我有一个代码库,它开始像这样: 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 <-

我是一个非常新手的OCaml程序员,所以如果这是一个愚蠢/明显的问题,请原谅我。有很多东西需要吸收,我可能在文档中遗漏了这一点

我有一个代码库,它开始像这样:

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 
let update_scalar p scalar value =
    add_delta p;
    magic_reflection (p, scalar) <- value;
    refresh p

这对我来说是“宏”,但我不相信OCaml有宏系统。我还能做什么?

不,在普通的OCaml中,你不能做你想做的事情。您可以编写一个语法扩展(这是一种宏系统,尽管可能与您习惯的不同),它可以转换

UPDATE_FIELD x f y
进入


x.f您不能完全随心所欲,但您可以使用高阶函数大大简化样板文件:

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)
让我们更新发电机组px=
加上δp;
设px;
刷新p

如上所述,让update_x=update_gen(fun p v->p.x p.y p.z)ocaml具有宏系统。对于此任务,只需要一小部分:

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
请参阅生成的代码,其中包含:

camlp4o Camlp4MacroParser.cmo q.ml

Nit:选择
val
作为标识符名称是令人困惑的,
val
被用作模块类型中的绑定。这在大多数情况下都是正确的解决方案。如果有必要,您可以随时优化您的代码。无论如何,帮我们一个忙,不要开始依赖camlp4,这是一堆废话。
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
ocamlfind ocamlc -package camlp4.macro -syntax camlp4o q.ml -o q
camlp4o Camlp4MacroParser.cmo q.ml