Теоретически самое короткое, с чем вы можете сойти с рук:
frobnicate (function
| 0x01 -> gets , a_record_uuid
| 0x02 -> gets , a_group
...
)
Конечно, вы будете сорваны OCaml, потому что 1 ° в Objective Caml нет конструкций «указатель на член», поэтому вам придется написать fun a s -> a.a_record_uuid <- s
вместо a_record_uuid
(как минимум) и 2 ° система типов не полностью поддерживает экзистенциальную количественную оценку, поэтому тип возвращаемой функции не может быть ожидаемым:
exists 'a. int -> (unit -> record * 'a) * ('a -> record -> unit)
Полагаю, вы могли бы решить 1 °, назвав функции для установки значений в записи, если вам случится сделать это достаточно часто:
type complex = { re : int ; im : int }
let re r c = { c with re = r }
let im r c = { c with im = i }
Думаю, это немного неортодоксально, но обычно это окупается позже, потому что я склонен использовать их в большинстве функциональных ситуаций. Вы можете создать эквивалент в императивном стиле или принять служебную нагрузку на функцию (она добавляет только около 20 символов).
Как или 2 °, это можно решить, скрыв квантор существования в функции:
let t e read write = let c, x = read () in write x e ; `More_record c
Это позволит вам перейти к:
let t = t a in
match
| 0x01 -> t gets a_record_uuid
| 0x02 -> t gets a_title
...
Я не удивлюсь, если CamlP4 поддержит какой-то сахар для функций присваивания. В то же время, если вы используете ссылки вместо изменяемых полей, вы можете сократить их (поскольку ссылки являются значениями первого класса, а поля нет):
let t read reference = let c, x = read () in reference := x ; `More_record c
match
| 0x01 -> t gets a.a_record_uuid
...