September 07, 2001
I've pretty much settled on the array.length=newlength version. Such also fits in with the idea of a property assignment being a "put", which can be a function call.

There are actually two dimensions to a dynamic array - the used length and the allocated length, with used<=alloced. The implementation only carries around the used length as the .length property. The alloced length is only known to the garbage collector.

Resizing an array therefore must be integrated with the collector implementation, so it could be reallocated in place, without copying, when possible.

Another poster mentioned that the alloced length for a resizable array should go in increments of powers of 2, I have empirically found this to be most appropriate in my own work. Thus, dynamic arrays will be allocated in power of 2 buckets, so resizing them will only require a copy operation if it grows or shrinks over a power of 2 size.

a wrote in message <3B984E93.4A154FA4@b.c>...
> A lot of people seem to think a lot of things.  I think the question
>got over interpreted.  Walter, would it be safe to say that dynamic arrays are not like other languages' Vector classes or script languages' dynamic arrays?  Specifically in that D's dynamic arrays don't try to provide enhanced appending, prepending, truncation, splicing or manage how much space is allocated vs. used?
> Perhaps it would be safer for folks to think of a dynamic array in D as
>a C dynamically allocated array that knows how much space it has allocated?  Given that, it might be nice to have resizing done with a property.  A method is apparently making people think that this is a class with all sorts of nice features that it is not supposed to provide.  Instead it is a basic type that abstracts way a very common and error prone operation, realloc, so you can implement all of these other wonderful abstractions with less worry.  Of course since realloc is definitely an operation and not a trivial one, it would imply a method would be the way to go.  How am I doing so far?
> In the end, property or method, I don't really care.  I guess I would
>like the syntax that uses less typing, since I'm comfortable with the operation that's happening.  I'm content with either, but I do think that this thread has gone overboard with great expectations for a very simple type & abstraction.  Are my expectation too low for what was intended of the dynamic array?
>
> I would like a syntax that could do a resize in-place since the runtime
>memory management system could probably do it when space allows. (Realloc works this way on most systems, right?)  Forcing a reassignment would almost guarantee a copy whether or not it was really needed. Also, I would assume that any resize operation could potentially throw an exception.  If so, then that should probably be considered with respect to the whole exception specification issue.
>
> I guess I'll take the opportunity to provide another nudge for some
>form of overloading while I'm at it.  If in fact D's dynamic arrays are meant to be merely the primitive used to create these other spectacular container types that people clamor for, it would be nice if the higher level containers could have a square brace operator.
>
>Dan
>
>
>Walter wrote:
>>
>> I've gone back and forth on this issue (whether setting .length resizes
the
>> array, or is it read-only). What do y'all think?
>>
>> Russ Lewis wrote in message <3B96A34F.DABE45E5@deming-os.org>...
>> >I'm assuming that the .length property of a dynamic array can be set, causing the code to change the size, right?  This is not specified in the spec, that I can see.
>> >
>> >Also, I assume that such a resize operation can (if expanding) result in an out-of-memory exception being thrown, just like operator new.  I don't see specs for either of those...
>> >


September 07, 2001
Walter wrote:

> Russ Lewis wrote in message <3B980568.6E0E71EC@deming-os.org>...
> >size would be a good choice, but it's already a parameter that works a lot
> like a
> >dynamic sizeof:
> >int[] array = {3,4,5};
> >int len = array.length; /* returns 3 */
> >int size = array.size; /* returns 12, if you assume 32bit ints */
>
> Actually, no, .size returns 8 for arrays. The reason is because that's how much storage the reference takes up. .size doesn't refer to how much space the actual data in the array consumes.
>
> The reason it is this way is so you can sum the .size's of, say, a struct's members and arrive at the .size of the struct (assuming 1 byte alignment). Doing otherwise would lead to ambiguities, like what would the .size be for an array of arrays?
>
> To get the size of the data bytes in the array:
>
>     array.length * array[0].size

My mistake, sorry :)


September 07, 2001
Russ Lewis wrote:

> Charles Hixson wrote:
> 
> 
>>I was actually talking about using a substring *without* taking
>>it out of the string.  Sort of a safe version of C's pointer to
>>char variable.  You might be able to declare that:
>>char [] inline;
>>declare inline [1,15] user_id;
>>declare inline [16, 29] first_name;
>>declare inline [35, 50] last_name;
>>declare inline [16, 60] full_name;
>>...
>>
> 
> Right, my understanding is that you could do the following:
> 
> void foo(char[] data)  // data is passed by reference, NOT value
> {
>    char[] user_id = data[1..15];
>    char[] first_name = data[16..29];
>    char[] last_name = data[35..50];
>    char[] full_name = data[16..60];
> 
>    user_id = data[1..15];
>    first_name = data[16..29];
>    last_name = data[35..50];
>    full_name = data[16..60];
>    ...
> };
> 
> As I understand it, none of this does any string copying.  All of the field arrays
> point into the main array (and, BTW, count as references to the main array - so you
> won't get garbage collected at the wrong time).
> 
> 
>>the_name = trim (last_name) + ", " + trim (first_name)
>>
> 
> Similarly, the beauty of D dynamic arrays is that the trim function can return an
> array that points into the original argument but has a different length.  Once it is
> used in the concatenation process, that reference to the array goes away
> automagically....
> 
> 

Thanks, that sounds like *just* what I was asking for!  (And a bit more, as it can be passed as a parameter.)  (And a bit less, as the original string isn't "safe" from the references.)

September 07, 2001
Walter wrote:
> Another poster mentioned that the alloced length for a resizable array should go in increments of powers of 2, I have empirically found this to be most appropriate in my own work. Thus, dynamic arrays will be allocated in power of 2 buckets, so resizing them will only require a copy operation if it grows or shrinks over a power of 2 size.

This is very sensible for moderately-sized arrays. It's very wasteful for very large arrays. May I recommend power-of-two doubling up to somewhere in the 16K to 256K range, then a linear incrementage after that?

-Russell B
September 07, 2001
Walter, I understand that D provides strings, dynamic and associative arrays with an added benefit in terms of syntax, but my point is that you should provide them as standard library containers.

The added syntactic sugar could be achieved with some form of meta-language definition feature. In this case, I'm proposing a major feature of the D language that allows the user to build himself these kinds of data structures.

For example, if I want to build a, say, red-black tree container. How am I supposed to do that in D ? Can I add new keywords to support it, overload operators ? More importantly can I do it on a type safe way ?

This is why major language features are more important than minor syntactic issues. Templates in c++ have more uses than even Bjarne Stroustrup himself would thought possible! It serves more than one use. It is a generic programming supporting tool instead of being a dedicated problem solver. Major features allow for extensions and encourage a generic programming style.

With these specs, I really don't think this is a systems programming language. Built-in data structures, heap allocated data, garbage collection, no generic programming facilities. All this is more consistent with a language oriented to services programming. Perhaps you should consider calling D something more closely to the Java family. I expect a much larger degree of success if it is targeted to this area.

-Rui


September 07, 2001
"Rui Ferreira" <t5rui@hotmail.com> wrote in message news:9nb494$1mg4$1@digitaldaemon.com...
> Walter, I understand that D provides strings, dynamic and associative
arrays
> with an added benefit in terms of syntax, but my point is that you should provide them as standard library containers.

These facilities are not implementable in C without ugly syntax, and implementing them in C++ requires a vast and complex language to support meta programming (STL). Furthermore, the C++ way allows one to implement dynamic arrays in 64000 different and incompatible ways. Providing a builtin dynamic array facility that covers 95% of the needs for such means that your array code is portable from programmer Bob to programmer Fred. (So what I'm addressing is not simply portability from compiler to compiler, but from *programmer* to programmer.)

> This is why major language features are more important than minor
syntactic
> issues.

With every data type, the language designer must decide if it is built in or if it's part of a runtime library. I feel the advantages of dynamic arrays outweigh the disadvantages of them being fixed by the language implementation. Dynamic arrays are a regular feature of my C++ coding, and I'm tired of the tedium, bugs, etc., involved in writing implementation after implementation of them. I'm tired of messing about with strings. I'm tired of buffer overflows. Building dymanic arrays into the language just chucks all that.

C's support for strings is just plain inadequate. Java has halfway builtin arrays, and halfway builtin strings. Java strings are not Java arrays. The way Java strings are done is a serious performance hit. D's design makes strings a special case of arrays. They should be much faster than C arrays and require less memory. They're easier to write, the syntax does what you'd expect, and the possibility for bugs is greatly reduced.

> Templates in c++ have more uses than even Bjarne Stroustrup himself would thought possible! It serves more than one use. It is a generic programming supporting tool instead of being a dedicated problem solver. Major features allow for extensions and encourage a generic programming style.

I am consistently amazed by what people manage to do with C++ templates. I consider it a defect in C++, however, that a massive template library and an enormously complex language is required just to implement a string type.

> With these specs, I really don't think this is a systems programming language. Built-in data structures, heap allocated data, garbage
collection,
> no generic programming facilities. All this is more consistent with a language oriented to services programming. Perhaps you should consider calling D something more closely to the Java family. I expect a much
larger
> degree of success if it is targeted to this area.

D still allows the programmer to get "down and dirty", after all, it supports pointers and arbitrary casts. That capability is what distinguishes it from service langauges like Java, which go to great lengths to prevent that. Down and dirty capability makes it a systems programming language. What makes it better than C or C++ is that it is not necessary to get down and dirty for the vast majority of programming chores. For example, in D one can "map" a bit array across an int:

    int foo;
    bit[32] flags = *(bit[32] *)&foo;

Try that in Java.


September 07, 2001
> D still allows the programmer to get "down and dirty", after all, it supports pointers and arbitrary casts. That capability is what distinguishes it from service langauges like Java, which go to great lengths to prevent that. Down and dirty capability makes it a systems programming language. What makes it better than C or C++ is that it is not necessary to get down and dirty for the vast majority of programming chores. For example, in D one can "map" a bit array across an int:

Well but you know that in operating systems kernel you don't have a malloc or a free? So for beeing systems language, the idea C was invented for, what you do with dynamic arrays there? Or how do you make instances after all if creation on stack is not allowed? I know linux in example has a kmalloc and a kfree, that behave up to 90% the same, but the 10% difference are important to know to make good kernel code. (ie. the roundings that occour due to the buddy algorithmn). Even more criticial are things during the boot phase, well at first instance you don't have a stack at all, okay there all systems require assembler in the first steps. Okay then you've a stack but for long absolute no heap. In example linux has as next step a prelimarary memory managment, needed and available only temporary until later phase, where the buddy system is ready to go up. And even in the final kernel phase you sometimes want to get you data through other techniques like valloc() instead of malloc, because you need it physical constant, etc. this all managmentable in C, beeing a systems language.

A language that creates from itself calls to malloc and free during creation is at least in my eyes not suitable to write kernels, a libc library (which implements malloc after all), or some os-less embedded systems. This features are great to have in a pure user-space language, but this is against the idea what I've of a system language, and the original intention behind C.

- Axel
September 07, 2001
Axel Kittenberger wrote:

> A language that creates from itself calls to malloc and free during creation is at least in my eyes not suitable to write kernels, a libc library (which implements malloc after all), or some os-less embedded systems. This features are great to have in a pure user-space language, but this is against the idea what I've of a system language, and the original intention behind C.

It seems like it should be possible to write a D program without using any dynamic arrays.  If so, then you could implement a compiler switch that disabled them altogether.

You'd probably need to disable the garbage collector, as well.

If the two were possible (in some future version of the compiler), would you think D was kernel-ready?

September 08, 2001
Axel Kittenberger wrote in message <9nbaf7$1q6m$1@digitaldaemon.com>...
>Well but you know that in operating systems kernel you don't have a malloc or a free?

So don't use dynamic arrays for such code. Nothing prevents you from using
my_malloc() and my_free().



September 08, 2001
Russell Bornschlegel wrote in message <3B990850.73590841@estarcion.com>...
>Walter wrote:
>> Another poster mentioned that the alloced length for a resizable array should go in increments of powers of 2, I have empirically found this to
be
>> most appropriate in my own work. Thus, dynamic arrays will be allocated
in
>> power of 2 buckets, so resizing them will only require a copy operation
if
>> it grows or shrinks over a power of 2 size.
>This is very sensible for moderately-sized arrays. It's very wasteful for very large arrays. May I recommend power-of-two doubling up to somewhere in the 16K to 256K range, then a linear incrementage after that?


The power of 2 allocation goes up to 4k, and then is rounded up to the next 4k size.