From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by walapai.inria.fr (8.13.6/8.13.6) with ESMTP id p1GNr6fj020730 for ; Thu, 17 Feb 2011 00:53:06 +0100 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AssDAGbyW03RVaE0dGdsb2JhbACmBggVAQwJDAcNAgYgomuKDoIbhQMviFoBAQMFhVkEhQiHAohCOg X-IronPort-AV: E=Sophos;i="4.60,482,1291590000"; d="scan'208";a="91469525" Received: from mail-fx0-f52.google.com ([209.85.161.52]) by mail2-smtp-roc.national.inria.fr with ESMTP/TLS/RC4-SHA; 17 Feb 2011 00:53:02 +0100 Received: by fxm5 with SMTP id 5so2038343fxm.39 for ; Wed, 16 Feb 2011 15:53:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:date:message-id:subject:from:to :content-type; bh=rjDjdMq3gO/Qzzht7R3w5THkmtidx4px4mmNt7WyYEs=; b=dsUtRMoSOcw+UtT5TmhxVLYdz0igGClRruL3HuriJeUI1fhkRCytYVAwner6F3GrGH thjHZYDCHARZ6H/cuw7C2jUJTb+k7eQJEcsRPZqv5DXRmfqflbt8C0CfuWwAnrseX9G7 FblT1O2iZtalsX+6QegNrvGlZLpxjEM2fm7kM= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type; b=rlWdRuogiXJCIOq+iI+RJUCnxLdT1uig9/V4+vKQz5mGDjfiL+/EqHpTuh8bEqT1rc pe8RVQB6JTE4xNzLXtNS8+XWvNZahnzuoLiA6KEU4NMS9O50k3aKtLyFzx69ZMjgUTED amNqtgghBYeX7G/ZnT4aAMr/nxcr3dmnFWg14= MIME-Version: 1.0 Received: by 10.223.100.8 with SMTP id w8mr1506054fan.55.1297900382126; Wed, 16 Feb 2011 15:53:02 -0800 (PST) Received: by 10.223.24.218 with HTTP; Wed, 16 Feb 2011 15:53:02 -0800 (PST) Date: Wed, 16 Feb 2011 16:53:02 -0700 Message-ID: From: Anthony Tavener To: caml-list@yquem.inria.fr Content-Type: multipart/alternative; boundary=20cf3054a62d3b050c049c6efbbb Subject: [Caml-list] Common code over different fields of a record, using macros? --20cf3054a62d3b050c049c6efbbb Content-Type: text/plain; charset=ISO-8859-1 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 --20cf3054a62d3b050c049c6efbbb Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable I find that records often result in redundant code... the same operation be= ing specified for different fields (of the same type). I could use arrays i= n 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 t= o work if I update mutable fields (record.field <- x), but using the fun= ctional record-update {record with field=3Dx} doesn't work...


--- Simplified mock-up of my current situation (not enough to compi= le) ---

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

(* macro which doesn't work... "field" which follows &quo= t;with" doesn't get replaced *)
DEFINE AGE(field) =3D fun (stat= e,age) ->
=A0 let s,a =3D age_stat state.field age.field in
=A0 {s= tate with field=3Ds}, {age with field=3Da}

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

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

---

Afte= r processing by camlp4 with macros this is what the first case becomes:

=A0 | 1 -> let s,a =3D age_stat state.strength age.strength in
= =A0=A0=A0=A0=A0=A0=A0=A0 {state with field=3Ds}, {age with field=3Da}
"field" isn't replaced with "strength" in the rec= ord-update. I tried looking at Camlp4MacroParser.ml... but it makes my head= swim. It must be doing something much more careful than literal text repla= cement, but perhaps too careful... or incomplete? Does anyone know how thes= e macros work? Is this proper behavior for some reason, or an unhandled edg= e case?

The problem is I don't want a block of code like this to be repeate= d 10 times with only a field-name change for each (and 4 field names each t= ime!). 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!

=A0Tony

--20cf3054a62d3b050c049c6efbbb--