可以记录OCaml中的字段更新吗?

时间:2008-10-19 00:18:28

标签: 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 <- z;
  refresh p 

复制开始让我感到烦恼,因为我希望写下这样的东西:

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

这样当我更新x时我可以简单地调用:

update_scalar p 'x' value

这就是“宏!”对我而言,我不相信OCaml有一个宏系统。我还能做什么?

3 个答案:

答案 0 :(得分:5)

你无法做到你想要的,但你可以通过更高阶的功能大大减少样板:

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确实有一个宏系统(camlp4),它确实允许你实现这类工作,但有些工作。

答案 1 :(得分:1)

不,你不能在普通的OCaml中做你想做的事。您可以使用camlp4编写一个语法扩展(这是一种宏系统,虽然这种方式与您可能习惯的类型不同)会转换

UPDATE_FIELD x f y

x.f <- y

或者,您可以将内容填充到哈希表中并放弃类型安全。

注意:OCaml 3.10及更高版本中包含的camlp4版本与先前版本不同且不兼容。有关最新版本的信息,请参阅the OCaml tutorial site

答案 2 :(得分:0)

如上所述,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

编译:

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

使用以下命令查看生成的代码:

camlp4o Camlp4MacroParser.cmo q.ml