|
Boost : |
From: John Max Skaller (skaller_at_[hidden])
Date: 2001-07-17 13:49:02
Jens Maurer wrote:
>
> John Max Skaller wrote:
> > I seek your opinion on get/set vs. get/ref.
> Unless there is a very good, specific reason to use a "ref"
> member returning a reference, I'd always prefer a "set"
> interface for writing data into an object.
Here's the problem. Consider:
struct X { a: int; };
var x : X;
x.a = 1;
Felix represents all data structures, including structs,
by abstraction. At present, this is desugared by the parser
to read (more or less)
type X;
fun get_a: X -> int;
fun ref_a: &X -> ∫ // &T means 'pointer to T'
var x:X;
set(ref_a(&x),1);
Using get/set
type X;
fun get_a: X ->int;
proc set_a: &X * int; // T1 * T2 is a tuple
var x:X;
// set_a(&X,1);
The problem is how to translate
x.a = 1
into
set_a(&X,1)
Currently
lhs = rhs
is translated to
set(&lhs,rhs)
and
&x.a
is translated to
ref_a (&x)
and so we obtain
set(ref_a(&x),1)
by composition. The compiler has to know '&x.a' and translate it.
But using set methods, it has to know 'x.a='.
An equivalent problem: consider the procedure:
proc doubl (a:&int) { *a = *a + *a; }
If there is no way to reference the 'a' component of X,
you will NOT be able to call
doubl(&x.a);
You will have to write:
val tmp = x.a;
doubl(&tmp);
x.a = tmp;
> C++ iterators have gone the "reference" way (i.e. operator*
> usually returns a reference), and it causes grief in various
> aspects: std::vector<bool> is not a container any more,
Yes. But consider the flip side. Suppose you have a
vector of X. Then you can write, at present:
(*iterator).a++;
precisely because *iterator IS a reference. If you had get/set methods,
you'd have to write:
X x = iterator->get();
x.a++;
iterator->set(x);
> (There was at least one good reason for iterators going the
> "reference" way: They imitate raw pointers and therefore
> feel more comfortable and natural to some programmers.)
See above. There is a lot more at stake here than
imitating raw pointer syntax. The problem is that references
act to decouple mutators into addressability and subobject
mutation. Without it, you get OO lunacy: a get and set
method for every member of a struct. Thats fine
for a single struct, but if the objects inside the
struct are also structs, you get a choice:
1) an explosion of get/set methods: export inner
methods to the top level
2) manual decoupling on use: get the outer object,
get the inner subobject .. mutate it, set it back ..
(as illustrated).
Note that Felix doesn't have a problem with (1) generating
all the methods. The problem is _naming_ them so that they
can be used.
The user, on the other hand, may have problems with (2).
[Despite my comments, I tend to favour get/set. However,
Felix _is_ intended for C++ programmers who seek a
very high level language they can learn in a day,
and which can be used with their existing C++ code
with very little effort]
-- John (Max) Skaller, mailto:skaller_at_[hidden] 10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850 New generation programming language Felix http://felix.sourceforge.net Literate Programming tool Interscript http://Interscript.sourceforge.net
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk