suggestion: read-only array-reference

Hasan Aljudy hasan.aljudy at gmail.com
Wed Jul 19 05:25:12 PDT 2006


I've posted a draft of this proposal on D.Learn but I think not many 
people visit there, plus this time it's a bit simplified.

This is a suggestion that aims to guarantee compile-time "read-only" 
correctness for arrays passed to and/or returned from functions.

Introduce a new type of array-reference, that proveds "read-only" 
interface to the contents of the array.

I'm using the term "array reference" because array types in D are 
actually references.

This proposed reference is a new type, that's strongly enforces by the 
compiler.

You can make a read-only array reference refer to any array (including 
slices, of course) but this reference doesn't provide any methods to 
modify the content of the array, not its length.

Any normal array can be converted/casted to a read-only reference, but 
read only references cannot be casted to anything; never.

More over, normal array references should be implicitly castable to 
read-only array referencs.
Normal arrays should provide a property "readonly" that returns a 
read-only reference to the array.
so, if xyz is an array, then xyz.readonly returns a read-only reference 
to xyz.

Of course, if you hold a normal reference to an array that's also 
referred to by a read only reference, you can still change the array 
using the normal reference, but that's not the point.

The point is, you can pass the read-only reference to functions, knowing 
for sure that these functions cannot change the array. More over, this 
guarantee is enforced by the compiler at compile-time.

Just like the compiler will not let you call
foo.bar();
if foo doesn't expose a method called bar().
The compiler will not let you call
abc[4] = 'h';
if the abc is a read-only reference.

The proposed read-only reference allows you to:
-read elements from the array and iterate over them
-read a slice (the slice operation returns a read-only reference)
-read the length
-let it refer to another array

It doesn't allow you to:
-write to/change any element
-write to/change any property
-get a pointer to the array
-cast it to a normal array


It's basically something like the following class, but built into the 
language as another array type:
class ReadOnlyArrayReference(T)
{
	private:
	T[] array; //internal array reference
	
	public:

	this()
	{
	}
		
	this( T[] a )
	{
		array = a;
	}

	void set( T[] a )
	{
		array = a;
	}

	typeof(array.length) length()
	{
		return array.length;
	}

	typeof(array.dup) dup()
	{
		return array.dup;
	}

	typeof(array[0]) opIndex( int i )
	{
		return array[i];
	}

	typeof(this) opSlice( int i, int j )
	{
		return new ReadOnlyArrayReference(array[i..j]);
	}

         //probably some more ...
}

It's just a wrapper around an array, but it hides the actual array 
reference and doesn't provide any interface for changing the contents of 
the array.

Of course, if the array contains object references, then you cannot 
change the references, but you can still change the objects themselves 
using the references.
However, I believe that's not a big issue.

The only thing that I can't figure out is what syntax is appropriate.
Currently, we use [] to declare arrays:

type[] x; //x is a reference to an array.

Maybe we can use [!] to declare read only references:
type[!] x; //x is a read-only reference to an array.
or something like that.

It should still be OK to create complicated types, like:

type[!][3] x; // x is an array of 3 read-only array references

and so on ...

If this gets implemented, then phobos could be rewritten to always take 
read-only references to char arrays (strings) and the such.
This implies that COW protocol wouldn't be needed, since you can't write 
to these arrays anyway.

Examples of usage:
--------------
//assume abc is already declared as a read-only reference to a char array
//holding the string "hello";

char c = abc[3]; //ok, you can read elements
abc[2] = 'x'; //error, can't write to elements
auto x = abc.ptr; //error, can't get pointer and/or no such property
abc.length = 7; //error, can't write to a property and/or not set method 
exists for property "length"
abc = "audi"; //ok, abc now refers to another array, the original
               //string "hello" remains intact.
auto r = abc.length; //ok, you can read the length property
char[] b = abc; //error, cast not allowed.
char[] b = abc.dub; //ok, duplicating produces a normal array reference 
.to the duplicated array
foreach( a; abc ) //ok, you can iterate over the array
{
  ....
}
------------

all errors indicated above are compile-time errors.



More information about the Digitalmars-d mailing list