www.digitalmars.com         C & C++   DMDScript  

D - language limitations?

reply Norbert Nemec <Norbert.Nemec gmx.de> writes:
Hi there,

I just tried to scribble an implementation of multidimensional arrays. (See
below).

As you can see, I chose "struct" over "class" for the Array, since Array
itself is basically an extended pointer to the array data. Putting it on
the heap as an object of a class and handling a reference to it would mean
additional overhead and strange semantics.

Now there are a few limitations I could not overcome yet:

* structs cannot have a constructor and seem generally rather limited. I do
not propose to add everything to a struct that a class has (like that
C++-stupidity of struct vs. class) but I would still like to think of them
as "lightweight" classes. (I.e. stored on the stack, no virtual members,
but full encapsulation etc.)

* array literals are badly missing - or, even better - "array expressions",
that are not limited to constant entries.

* lvalues (i.e. references) as return-values of functions would help avoid
duplicating code and give more flexibility.

Any ideas?

Ciao,
Nobbi

---------------------------------------
alias size_t idx_t;
alias ptrdiff_t stride_t;

struct slice_t {
        idx min;
        idx max; // actually max + 1
        stride_t stride;
};

struct Array(T,uint DIM) {
        private T* data; // not a T[] because stride might be negative
        private idx_t range[DIM];
        private stride_t stride[DIM];
        
        void constructor(idx_t[DIM] r) {
                range[] = r[];
                uint size = 1;
                for(uint d=DIM;d--;) {
                        stride[d] = size;
                        size *= range[d];
                };
                data = new T[size];
        };
        
        private T* ptr(idx_t[DIM] i)
        in {
                foreach(uint d,idx_t id;i) {
                        assert(id < range[d]);
                };
        } body {
                int offset = 0;
                foreach(uint d,idx_t id;i) {
                        offset += id*stride[d];
                };
                return &data[offset];
        };
        
        T opIndex(idx_t[DIM] i) {
                return *ptr(i);
        };

        T opIndex(idx_t[DIM] i, T value) {
                return *ptr(i) = value;
        };

        .Array!(T,DIM) slice(slice_t[DIM] sl)
        in {
                foreach(uint d,slice_t s;sl) {
                        assert(s.min <= s.max);
                        assert(s.max <= range[d]);
                        assert(s.stride > 0);
                                // negative strides not yet implemented
                };
        } body {
                .Array!(T,DIM) res;
                idx_t[DIM] min_idx;
                foreach(uint d,slice_t s;sl) {
                        res.range[d] = (s.max-s.min + s.stride - 1) / s.stride;
                        res.stride[d] = stride[d] *  s.stride;
                        min_idx[d] = s.min;
                };
                res.data = ptr(min_idx);
                return res;
        };
};

int
main() {
        static idx_t[2] range = [3,4];

        Array!(real,2) a;
        a.constructor(range);
        
        static idx_t[2] a_idx = [2,1];
        
        a[a_idx] = 1.5;

        static slice_t[2] myslice = [{min:0,max:3,stride:2},
                                     {min:1,max:4,stride:2}];
        
        Array!(real,2) b = a.slice(myslice);

        static idx_t[2] b_idx = [1,0];
        
        b[b_idx] = b[b_idx] * 3;

        printf("%Lg\n",a[a_idx]); // should show 4.5
        
        return 0;
};
--------------------------------------
Apr 24 2004
parent Ben Hinkle <bhinkle4 juno.com> writes:
 Now there are a few limitations I could not overcome yet:
 
 * structs cannot have a constructor and seem generally rather limited. I
 do not propose to add everything to a struct that a class has (like that
 C++-stupidity of struct vs. class) but I would still like to think of them
 as "lightweight" classes. (I.e. stored on the stack, no virtual members,
 but full encapsulation etc.)

There's a nifty technique using opCall to write struct "constructors". I haven't tried using it with templates but you might give it a try. I added an example of this technique to dsource: http://www.dsource.org/tutorials/index.php?show_example=70 -Ben
Apr 24 2004