Read-only array reference (was: Re: Clarifying 'const' terminology)

Hasan Aljudy hasan.aljudy at gmail.com
Fri Jul 7 19:57:45 PDT 2006



kris wrote:
> Good idea ~ I'll have a go:
> 
> Derek Parnell wrote:
> 
>> I'm not from a C++/C#/Java background, so please excuse my lack of  
>> understanding about the meaning that is being applied to the term 
>> 'const'  in these recent discussions.

I am from a C++/Java background, yet I still don't fully understand const!
The only thing I understand is that Java doesn't need it because it's 
higher-level than D, doesn't allow pointer manipulation, and has builtin 
immutable String class.

I still don't understand why D needs it, or why do some people think so.

> <snip>
>> My requirements for 'const' are almost covered by Walter's new 
>> proposal.  I'm a quite concerned that if I tell Foo() that it can't 
>> change something,  that Foo() can still tell Bar() to disregard my 
>> request and tell Bar()  that it's okay to change it anyway.
> 
> 
> 
> Yes, that is a notable weakness. Using an aggregate (struct or class) 
> instead would give you the /propogation/ aspect required. This is in 
> contrast to Walter's proposal, but requires the use of aggregates rather 
> than, say, an array. BTW: this whole discussion is basically about array 
> types, since others can happily be passed by value anyway.


Then how about introducing a new type: read-only array reference.
(The idea is inspired by Java's immutable string class)

It would be a distinct type, but built into the language core.
It has a different declaration syntax from regular arrays.
It cannot be casted to anything at all, absolutly no pointer 
manipulation is allowed either.
The content of the array cannot be modified (further explanation below).
The reference itself *can* be modified to refer to another array, but it 
would still be a read-only reference.
Any type of regular array reference (dynamic/static/associative) can be 
converted to a read-only array reference.

For example, the syntax could be:
int[$] x; //declare x as a readonly reference to an array of "int"s.

using the $ might not be the best thing, but please bare with me .. 
that's not the main point.

 From now on, I'm gonna assume there's a nice syntax that's consistent 
with the rest of the D language.

To ensure that the content of the array cannot be modified, some 
measures must be taken regarding what happens when you read an element 
from the array.

Let's agree first on some terminology:
Contained Type: if <code> T[$] x; </code> declares a read-only array 
reference to an array of T's, then T is the contained type.

Now, in theory, the contained type can either be
- a native type (int, float, byte ... enums .. etc)
- a struct
- a class (reference)
- an array or a pointer.

When an element is read from the array, what should we do?
- if the contained type is a native type or an enum, then a copy of the 
element is returned.
- if the contained type is a struct, then a copy is returned.

That's simple .. but what if the contained type is a class or an array?

Well, if it's a class, then it's a little bit complicated. I don't even 
know if we /need/ any kind of guarantees with an array of objects, but 
anyway!
Let's assume that we do need this guarantee, and let's take a step back.
The compiler shouldn't allow the contained type of a read-only array 
reference to be a class; instead, it should only allow it to be an 
interface that's derived from a generic (empty) interface called IReadOnly.

This measure will not allow the compiler to always ensure that objects 
contained in such a way cannot be modified, however, it gives the author 
of the class a guarantee that if he subclasses IReadOnly the right way, 
then his objects won't be modifiable.

Example:
------------------
interface IImmutableCircle : IReadOnly
{
     int radius();
}

class Circle : IImmutableCircle
{
    private int mradius;
public:
    int radius() { returm mradius; }
    void radius( int r ) { mradius = r; }
}

....

Circle[$] arr; // error, no class allowed as the contained type for a 
read-only reference
IImutableCircle[$] arr; //ok, since IImmutableCircle derives from IReadOnly
---------------------------

Of course the coder can mess up his code and add methods in 
IImmutableCircle that allow the object to be modified, but the important 
thing is that that's his own reponsibility; no user of his code can mess 
this up.

If there's a loop-hole in this approach, then disregard it. I'm starting 
to think that the whole issue of protecting objects is unneeded.

A similar approach can be taken if the contained type is an array.
Either prevent that and require it to be a read-only array reference, or 
allow it because preventing it is too complicated or just un-needed.

So, what do you think about this proposal?
Is it practical? Does it solve most of the const issues?
Does it even make sense, or is it just stupid all-together?

I was gonna post this as a new topic in the main D ng, but I thought it 
might have been proposed before, so I present it here instead.

> 
> The one problem with using aggregates in this manner is related to 
> return values. For example, you can make a String struct or class and 
> control what each method does to the encapsulated content. At some 
> point, though, the content will likely need exposing. Perhaps via a 
> toString() method or via some other means. Simply duplicating the 
> content at this point is a contentious issue, so some means of tagging 
> the return value as 'immutable', and having that usage enforced, would 
> seem to be necessary.

I think the above proposal should covers most of that.
The only thing left is adding a toReadOnlyString() to the Object class, 
or something like that.


A Java-like immutable string type can be declared with
char[$] x; // x is an immutable string!
Well, it's not really immutable, but the reference is read-only, so the 
string cannot be modified thru that reference.



More information about the Digitalmars-d-learn mailing list