Boost logo

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