Version française
Home     About     Download     Resources     Contact us    
Browse thread
[Caml-list] RFC: get/set vs get/ref
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Bruce Hoult <bruce@h...>
Subject: Re: [Caml-list] RFC: get/set vs get/ref
At 11:49 AM +1000 7/12/01, John Max Skaller wrote:
>The difference is exemplified by the following techniques
>for incrementing a character:
>
>	s.set ((s.get(pos) + 1),pos)  // get/set method
>	s.ref(pos).++                 // ref method
>
>Clearly, ref methods are more powerful and more efficient,

I don't think that warrants a "clearly".  Given good compilers *both* 
will be compiled down to a memory load, an add, and a memory store.

For example, in Dylan you can do the following (Dylan source, 
followed by C generated by the Gwydion d2c compiler, followed by PPC 
asm):

---------------------------------
module: getset

define class <foo> (<object>)
   slot x :: <integer>,
     required-init-keyword: x:
end;

define function bar(s :: <foo>) => ()
   s.x := s.x + 1
end function bar;
---------------------------------
#define SLOT(ptr, type, offset) (*(type *)((char *)ptr + offset))

void getsetZgetsetZbar_FUN(descriptor_t *orig_sp, heapptr_t A_s /* s */)
{
     descriptor_t *cluster_0_top;
     long L_x; /* x */
     L_x = SLOT(A_s, long, 4);
     SLOT(A_s, long, 4) = (L_x + 1);
     return;
}
---------------------------------
0x29f4 <getsetZgetsetZbar_FUN>:     lwz     r9,4(r4)
0x29f8 <getsetZgetsetZbar_FUN+4>:   addi    r9,r9,1
0x29fc <getsetZgetsetZbar_FUN+8>:   stw     r9,4(r4)
0x2a00 <getsetZgetsetZbar_FUN+12>:  blr
---------------------------------



>but on the other hand they expose the underlying implementation
>and prevent hooking changes to the mutable state.

Right.  For example, in Dylan you can modify the above example to the 
following (Dylan source, generated C code for bar(), asm for bar(), 
output):

---------------------------------
module: getset

define function report(a :: <foo>, b :: <integer>) => ()
   format-out("slot x was %=, now %=\n", a.x, b);
end;

define class <foo> (<object>)
   slot x :: <integer>,
     required-init-keyword: x:,
     setter: internal-update-x;
end;

define inline method x-setter(new :: <integer>, a :: <foo>)
   report(a, new);
   internal-update-x(new, a);
end;

define function bar(s :: <foo>) => ()
   s.x := s.x + 1
end bar;

begin
   let a = make(<foo>, x: 13);
   bar(a);
end
---------------------------------
void getsetZgetsetZbar_FUN(descriptor_t *orig_sp, heapptr_t A_s /* s */)
{
     descriptor_t *cluster_0_top;
     long L_x; /* x */
     long L_new_value; /* new-value */
     L_x = SLOT(A_s, long, 4);
     L_new_value = (L_x + 1);
     getsetZgetsetZreport_FUN(orig_sp, A_s, L_new_value);
     SLOT(A_s, long, 4) = L_new_value;
     return;
}
---------------------------------
0x28bc <getsetZgetsetZbar_FUN>:         mflr    r0
0x28c0 <getsetZgetsetZbar_FUN+4>:       stmw    r28,-16(r1)
0x28c4 <getsetZgetsetZbar_FUN+8>:       stw     r0,8(r1)
0x28c8 <getsetZgetsetZbar_FUN+12>:      stwu    r1,-80(r1)
0x28cc <getsetZgetsetZbar_FUN+16>:      mr      r28,r4
0x28d0 <getsetZgetsetZbar_FUN+20>:      lwz     r29,4(r28)
0x28d4 <getsetZgetsetZbar_FUN+24>:      addi    r29,r29,1
0x28d8 <getsetZgetsetZbar_FUN+28>:      mr      r5,r29
0x28dc <getsetZgetsetZbar_FUN+32>:      bl      0x2590 
<getsetZgetsetZreport_FUN>
0x28e0 <getsetZgetsetZbar_FUN+36>:      stw     r29,4(r28)
0x28e4 <getsetZgetsetZbar_FUN+40>:      lwz     r0,88(r1)
0x28e8 <getsetZgetsetZbar_FUN+44>:      addi    r1,r1,80
0x28ec <getsetZgetsetZbar_FUN+48>:      mtlr    r0
0x28f0 <getsetZgetsetZbar_FUN+52>:      lmw     r28,-16(r1)
0x28f4 <getsetZgetsetZbar_FUN+56>:      blr
---------------------------------
[localhost:~/programs/dylan/getset] bruce% ./getset
slot x was 13, now 14
---------------------------------



>What's the best technique?

get/set, I think.

With appropriate language support it can:

- have exactly the same syntax as traditional languages, with no ugly 
function notation for things that users think of as fields

- compile down to the exact same code that would be generated by 
languages such as C

- have the ability to transparently hook extra functionality such as 
format changes, monitoring, filtering into the getter and/or setter 
with no changes to the client code.


Sorry to post Caml-free stuff here :-(

-- Bruce
-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr