Можно ли обобщать записи полевых обновлений в OCaml? - PullRequest
3 голосов
/ 19 октября 2008

Я очень начинающий программист на 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 ]

5 голосов
/ 05 ноября 2008

Вы не можете делать то, что вы хотите, но вы можете значительно уменьшить шаблон с функцией более высокого порядка:

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 голос
/ 19 октября 2008

Нет, вы не можете делать то, что вы хотите, в простом OCaml. Вы можете написать расширение синтаксиса с помощью camlp4 (что является разновидностью макросистемы, хотя и отличается от той, к которой вы, вероятно, привыкли), которая преобразует

UPDATE_FIELD x f y

в

x.f <- y

Кроме того, вы можете положить вещи в хеш-таблицу и отказаться от безопасности типов.

ПРИМЕЧАНИЕ. Версия camlp4, включенная в версию 3.10 OCaml и более поздние, отличается от предыдущей версии и несовместима с ней. Для получения информации о последней версии см. учебный сайт OCaml .

0 голосов
/ 24 января 2011

Как отмечалось выше, в 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
...