Pode gravar atualizações de campo em OCaml ser generalizada?
Pergunta
Eu sou um novato muito OCaml programador então por favor me perdoe se esta é uma pergunta estúpida / óbvio. Há muito para absorver e eu possa ter perdido este na documentação.
Eu tenho uma base de código que está começando a olhar como este:
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
A duplicação está começando a me incomodar porque eu deseja para escrever algo como isto:
let update_scalar p scalar value =
add_delta p;
magic_reflection (p, scalar) <- value;
refresh p
Desta forma, quando eu atualizar x posso simplesmente chamar:
update_scalar p 'x' value
Esta chama "macros!" para mim, mas eu não acredito que OCaml tem um sistema de macro. O que mais eu posso fazer?
Solução
Não, você não pode fazer o que quiser em OCaml simples. Você poderia escrever uma extensão de sintaxe com camlp4 (que é uma espécie de um sistema de macro, embora de um tipo diferente do que você provavelmente está acostumado a) que transformaria
UPDATE_FIELD x f y
para
x.f <- y
Como alternativa, você poderia colocar as coisas em uma tabela hash e renunciar segurança de tipo.
NOTA: A versão do camlp4 incluído no OCaml versão 3.10 e posterior é diferente e incompatível com a versão anterior. Para obter informações sobre a versão mais recente, consulte o site OCaml tutorial .
Outras dicas
Você não pode fazer exatamente o que você quiser, mas você pode reduzir muito o clichê com uma função de ordem superior:
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 tem um sistema de macro (camlp4) e ele permite-lhe implementar esse tipo de coisa, com algum trabalho.
Como observado acima ocaml tem sistema de macro. E para esta tarefa é necessária apenas uma pequena fração dela:
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
Compilar com:
ocamlfind ocamlc -package camlp4.macro -syntax camlp4o q.ml -o q
Veja o código gerado com:
camlp4o Camlp4MacroParser.cmo q.ml