caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Anthony Tavener <anthony.tavener@gmail.com>
To: caml-list@yquem.inria.fr
Subject: [Caml-list] Common code over different fields of a record, using macros?
Date: Wed, 16 Feb 2011 16:53:02 -0700	[thread overview]
Message-ID: <AANLkTi=zPa35Wza-q1+XLennZ89sCzS8j+4rWgwz10w9@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 2484 bytes --]

I find that records often result in redundant code... the same operation
being specified for different fields (of the same type). I could use arrays
in these cases, but then lose meaningful (to programmers) field names.

I tried using camlp4 (and camlp5) macros to get the effect of passing a
field "name" to a "function". I could get my example to work if I update
mutable fields (record.field <- x), but using the functional record-update
{record with field=x} doesn't work...


--- Simplified mock-up of my current situation (not enough to compile) ---

(* a record with some fields of the same type... imagine there might be many
more fields *)
type stats = { strength: int; agility: int }

(* macro which doesn't work... "field" which follows "with" doesn't get
replaced *)
DEFINE AGE(field) = fun (state,age) ->
  let s,a = age_stat state.field age.field in
  {state with field=s}, {age with field=a}

(* val f : (stats * stats) -> int -> (stats * stats) *)
let age_character input = function
  | n when n < 2 -> input
  | 2 -> AGE(strength) input
  | 3 -> AGE(agility) input
  | _ -> AGE2(strength,agility) input

(* a mock-up of usage... *)
let state = { strength=3; agility=1 } in
let age = { strength=0; agility=0 } in
let state',age' = age_character (state,age) (rand 8) in ...

---

After processing by camlp4 with macros this is what the first case becomes:

  | 1 -> let s,a = age_stat state.strength age.strength in
         {state with field=s}, {age with field=a}

"field" isn't replaced with "strength" in the record-update. I tried looking
at Camlp4MacroParser.ml... but it makes my head swim. It must be doing
something much more careful than literal text replacement, but perhaps too
careful... or incomplete? Does anyone know how these macros work? Is this
proper behavior for some reason, or an unhandled edge case?

The problem is I don't want a block of code like this to be repeated 10
times with only a field-name change for each (and 4 field names each time!).
That's not well readable, prone to error, and harder to maintain properly.

Sometimes I wish I could present an alternative view of the same data, such
as having an array "view" into part of a record... verified to be typesafe
by the compiler... and compiled into the same simple offsets in the end.
Maybe it's my asm/C origins which I never seem to escape. I mention this in
hope that someone says "Oh, that's exactly what you can do... like this!" :)

Thank-you for any help caml-list!

 Tony

[-- Attachment #2: Type: text/html, Size: 2787 bytes --]

             reply	other threads:[~2011-02-16 23:53 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-02-16 23:53 Anthony Tavener [this message]
2011-02-18  9:11 ` Gabriel Scherer
2011-02-18 17:53   ` Anthony Tavener

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='AANLkTi=zPa35Wza-q1+XLennZ89sCzS8j+4rWgwz10w9@mail.gmail.com' \
    --to=anthony.tavener@gmail.com \
    --cc=caml-list@yquem.inria.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).