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